Ejemplo n.º 1
0
static bool
append_oxm_match_ipv6_addr( oxm_matches *matches, oxm_match_header header, struct in6_addr addr, struct in6_addr mask ) {
  assert( matches != NULL );

  uint8_t length = OXM_LENGTH( header );
  oxm_match_header *buf = xmalloc( sizeof( oxm_match_header ) + length );
  *buf = header;
  void *p = ( char * ) buf + sizeof( oxm_match_header );
  memcpy( p, &addr, sizeof( struct in6_addr ) );

  if ( OXM_HASMASK( header ) ) {
    p = ( char * ) p + sizeof( struct in6_addr );
    memcpy( p, &mask, sizeof( struct in6_addr ) );
  }

  return append_oxm_match( matches, buf );
}
Ejemplo n.º 2
0
/* Two flow matches overlap if there exists a packet which both match structures match on.
 * Conversely, two flow matches do not overlap if they share at least one match field with
 * incompatible value/mask fields that can't match any packet.
 */
bool
match_std_overlap(struct ofl_match *a, struct ofl_match *b, struct ofl_exp *exp)
{
	uint64_t all_mask[2] = {~0L, ~0L};

    struct ofl_match_tlv *f_a;
    struct ofl_match_tlv *f_b;
    int header, header_m;
    int field_len;
    uint8_t *val_a, *mask_a;
    uint8_t *val_b, *mask_b;

    /* Loop through the match fields in flow entry a */
    HMAP_FOR_EACH(f_a, struct ofl_match_tlv, hmap_node, &a->match_fields)
    {
        val_a = f_a->value;
        
        switch (OXM_VENDOR(f_a->header))
        {
            case (OFPXMC_OPENFLOW_BASIC):
                field_len = OXM_LENGTH(f_a->header); 
                if (OXM_HASMASK(f_a->header)) {
                    field_len /= 2;
                    header = (f_a->header & 0xfffffe00) | field_len;
                    header_m = f_a->header;
                    mask_a = f_a->value + field_len;
                } else {
                    header = f_a->header;
                    header_m = (f_a->header & 0xfffffe00) | 0x100 | (field_len << 1);
                    /* Set a dummy mask with all bits set to 0 (valid) */
                    mask_a = (uint8_t *) all_mask;
                }
                break;
            case (OFPXMC_EXPERIMENTER):
                if (exp == NULL || exp->field == NULL || exp->field->overlap_a == NULL) {
                    VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given.");
                    ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE);
                }
                exp->field->overlap_a(f_a, &field_len, &val_a, &mask_a, &header, &header_m, all_mask);
                break;
            default:
                break;
        } /*switch class*/

        /* Check presence of corresponding match field in flow entry b
         * Need to check for both masked and non-masked field */
        f_b = oxm_match_lookup(header, b);
        if (!f_b) f_b = oxm_match_lookup(header_m, b);

        if (f_b) {
            switch (OXM_VENDOR(f_b->header))
                {
                    case (OFPXMC_OPENFLOW_BASIC):
                        val_b = f_b->value;
                        if (OXM_HASMASK(f_b->header)) {
                            mask_b = f_b->value + field_len;
                        } else {
                            /* Set a dummy mask with all bits set to 0 (valid) */
                            mask_b = (uint8_t *) all_mask;
                        }                     
                        break;
                    case (OFPXMC_EXPERIMENTER):
                        if (exp == NULL || exp->field == NULL || exp->field->overlap_b == NULL) {
                            VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given.");
                            ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE);
                        }
                        exp->field->overlap_b(f_b, &field_len, &val_b, &mask_b, all_mask);
                        break;
                    default:
                        break;
                } /*switch class*/            

            switch (field_len) {
                case 1:
                    if (incompatible_8(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                case 2:
                    if (incompatible_16(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                case 4:
                    if (incompatible_32(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                case 6:
                    if (incompatible_48(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                case 8:
                    if (incompatible_64(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                case 16:
                    if (incompatible_128(val_a, val_b, mask_a, mask_b)) {
                        return false;
                    }
                    break;
                default:
                    /* Should never happen */
                    break;
            } /* switch (field_len) */

        } /* if (f_b) */

    } /* HMAP_FOR_EACH */

/* If we get here, none of the common match fields in a and b were found incompatible.
* The flow entries overlap */
return true;
}
Ejemplo n.º 3
0
/* Flow entry (a) matches flow entry (b) non-strictly if (a) matches whenever (b) matches.
 * Thus, flow (a) must not have more match fields than (b) and all match fields in (a) must
 * be equal or narrower in (b).
 * NOTE: Handling of bitmasked fields is not specified. In this implementation
 * a masked field of (a) matches the field of (b) if all masked bits of (b) are
 * also masked in (a), and for each unmasked bits of (b) , the bit is either
 * masked in (a), or is set to the same value in both matches.
 *
 */
bool
match_std_nonstrict(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;
    bool has_mask;

    /* Flow a is fully wildcarded */
    if (!a->header.length)
        return true;

    /* Loop through the match fields in flow entry a */
    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 */
        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_match->value + field_len;
                    flow_entry_mask = flow_entry_match->value + 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 (!nonstrict_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 (!nonstrict_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 (!nonstrict_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) {
                    if (!nonstrict_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 (!nonstrict_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 (!nonstrict_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 (!nonstrict_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 a were equal or wider than the ones in b */
    /* It doesn't matter if there are further fields in b */
    return true;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
/* Returns true if the fields in *packet matches the flow entry in *flow_match */
bool
packet_match(struct ofl_match *flow_match, struct ofl_match *packet, struct ofl_exp *exp){

    struct ofl_match_tlv *f;
    struct ofl_match_tlv *packet_f;
    bool has_mask;
    int field_len;
    int packet_header;
    uint8_t *flow_val, *flow_mask= NULL;
    uint8_t *packet_val;

    if (flow_match->header.length == 0)
        return true;
    
    /* Loop over the flow entry's match fields */
    HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &flow_match->match_fields)
    {
        /* Check presence of match field in packet */

        has_mask = OXM_HASMASK(f->header);
        packet_header = f->header;
        switch (OXM_VENDOR(f->header))
        {
            case(OFPXMC_OPENFLOW_BASIC):
                field_len =  OXM_LENGTH(f->header);
                flow_val = f->value;
                if (has_mask) {
                    /* Clear the has_mask bit and divide the field_len by two in the packet field header */
                    field_len /= 2;
                    packet_header &= 0xfffffe00;
                    packet_header |= field_len;
                    flow_mask = f->value + field_len;
                }
                break;

            case(OFPXMC_EXPERIMENTER):
                if (exp == NULL || exp->field == NULL || exp->field->match == 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(f, &packet_header, &field_len, &flow_val, &flow_mask);
                break;

            default:
                break;
        }
        
        /* Lookup the packet header */
        packet_f = oxm_match_lookup(packet_header, packet);
        if (!packet_f) {
        	if (f->header==OXM_OF_VLAN_VID &&
        			*((uint16_t *) f->value)==OFPVID_NONE) {
        		/* There is no VLAN tag, as required */
        		continue;
        	}
        	return false;
        }

        /* Compare the flow and packet field values, considering the mask, if any */
        switch (OXM_VENDOR(f->header))
        {
            case(OFPXMC_OPENFLOW_BASIC):
                packet_val = packet_f->value;
                break;
            case(OFPXMC_EXPERIMENTER):
                if (exp == NULL || exp->field == NULL || exp->field->compare == NULL) {
                    VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given.");
                    ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE);
                }
                exp->field->compare(f, packet_f, &packet_val);
                break;
            default:
                break;
        }

        switch (field_len) {
            case 1:
                if (has_mask) {
                    if (!match_mask8(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_8(flow_val, packet_val))
                        return false;                    
                }
                break;
            case 2:
                switch (packet_header) {
                    case OXM_OF_VLAN_VID: {
                        /* Special handling for VLAN ID */
                        uint16_t flow_vlan_id = *((uint16_t*) flow_val);
                        if (flow_vlan_id == OFPVID_NONE) {
                            /* Packet has a VLAN tag when none should be there */
                            return false;
                        } else if (flow_vlan_id == OFPVID_PRESENT) {
                            /* Any VLAN ID is acceptable. No further checks */
                        } else {
                            /* Check the VLAN ID */
                            flow_vlan_id &= VLAN_VID_MASK;
                            if (has_mask){
                                if (!match_mask16((uint8_t*) &flow_vlan_id, flow_mask, packet_val)){
                                    return false;
                                }
                            }
                            else {
                                if (!match_16((uint8_t*) &flow_vlan_id, packet_val)){
                                    return false;
                                }
                            }
                        }
                        break;
                    }
                    case OXM_OF_IPV6_EXTHDR: {
                        /* Special handling for IPv6 Extension header */
                        uint16_t flow_eh = *((uint16_t *) flow_val);
                        uint16_t packet_eh = *((uint16_t *) packet_val);
                        if ((flow_eh & packet_eh) != flow_eh) {
                            /* The packet doesn't have all extension headers specified in the flow */
                            return false;
                        }
                        break;
                    }
                    default:
                        if (has_mask) {
                            if (!match_mask16(flow_val, flow_mask, packet_val))
                                return false;
                        }
                        else {
                            if (!match_16(flow_val, packet_val))
                                return false;
                        }
                        break;
                }
                break;
            case 3:
                if (has_mask) {
                    if (!match_mask24(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_24(flow_val, packet_val))
                        return false;
                }
                break;
            case 4:
                if (has_mask) {
                    if (!match_mask32(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_32(flow_val, packet_val))
                        return false;
                }
                break;
            case 6:
                if (has_mask) {
                    if (!match_mask48(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_48(flow_val, packet_val))
                        return false;
                }
                break;
            case 8:
                if (has_mask) {
                    if (!match_mask64(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_64(flow_val, packet_val))
                        return false;
                }
                break;
            case 16:
                if (has_mask) {
                    if (!match_mask128(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_128(flow_val, packet_val))
                        return false;
                }
                break;
            default:
                /* Should never happen */
                break;
        }
    }
    /* If we get here, all match fields in the flow entry matched the packet */
    return true;
}
Ejemplo n.º 6
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);
	}
}
Ejemplo n.º 7
0
void 
print_oxm_tlv(FILE *stream, struct ofl_match_tlv *f, size_t *size){
                
                if (f->header == OXM_OF_IN_PORT){
                    fprintf(stream, "in_port=%d",*((uint32_t*) f->value));
                    *size -= 8;   
                    if (*size > 4)                                  
                        fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_IN_PHY_PORT){
                            fprintf(stream, "in_phy_port=%d",*((uint32_t*) f->value));
                            *size -= 8;   
                            if (*size > 4)                                  
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_VLAN_VID){
                            if ((uint16_t) *f->value == OFPVID_NONE)
                                fprintf(stream, "vlan_vid= none");
                            else if ((uint16_t) *f->value == OFPVID_PRESENT)
                                fprintf(stream, "vlan_vid= present");
                            else fprintf(stream, "vlan_vid= %d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_VLAN_PCP){
                            fprintf(stream, "vlan_pcp= %d", *f->value & 0x7);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_ETH_TYPE){
                            uint16_t *v = (uint16_t *) f->value;
                            fprintf(stream, "eth_type=0x");
                            fprintf(stream,"%x",  *v);
                            *size -= 6; 
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_TCP_SRC){
                            fprintf(stream, "tcp_src=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_TCP_DST){
                            fprintf(stream, "tcp_dst=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_UDP_SRC){
                            fprintf(stream, "udp_src=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_UDP_DST){
                            fprintf(stream, "udp_dst=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_SCTP_SRC){
                            fprintf(stream, "sctp_src=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_SCTP_DST){
                            fprintf(stream, "sctp_dst=%d",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                  
                else if (f->header == OXM_OF_ETH_SRC || f->header == OXM_OF_ETH_SRC_W){
                            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 (f->header == OXM_OF_ETH_DST || f->header == OXM_OF_ETH_DST_W){
                            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 (f->header == OXM_OF_IPV4_SRC || f->header == OXM_OF_IPV4_SRC_W){
                            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 (f->header == OXM_OF_IP_PROTO){
                            fprintf(stream, "ip_proto= %d", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_IP_DSCP){
                            fprintf(stream, "ip_dscp= %d", *f->value & 0x3f);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_IP_ECN){
                            fprintf(stream, "ip_ecn= %d", *f->value & 0x3);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_ICMPV4_TYPE){
                            fprintf(stream, "icmpv4_type= %d", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_ICMPV4_CODE){
                            fprintf(stream, "icmpv4_code= %d", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }   
                else if (f->header == OXM_OF_IPV4_DST || f->header == OXM_OF_IPV4_DST_W){
                            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 (f->header == OXM_OF_ARP_SPA || f->header == OXM_OF_ARP_SPA_W ){
                            fprintf(stream, "arp_sha=\""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 (f->header == OXM_OF_ARP_TPA || f->header == OXM_OF_ARP_TPA_W){
                            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 (f->header == OXM_OF_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 (f->header == OXM_OF_IPV6_SRC || f->header == OXM_OF_IPV6_SRC_W ){
                        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 (f->header == OXM_OF_IPV6_DST || f->header == OXM_OF_IPV6_DST_W){
                        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 (f->header == OXM_OF_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 (f->header == OXM_OF_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 (f->header == OXM_OF_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 (f->header == OXM_OF_IPV6_FLABEL){
                            uint32_t mask = 0xfffff;
                            fprintf(stream, "ipv6_flow_label=%x",((uint32_t) *f->value) & mask );
                            *size -= 8;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_ICMPV6_TYPE){
                            fprintf(stream, "icmpv6_type= %d", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_ICMPV6_CODE){
                            fprintf(stream, "icmpv6_code= %d", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_MPLS_LABEL){
                            uint32_t mask = 0xfffff;
                            fprintf(stream, "mpls_label=%x",((uint32_t) *f->value) & mask );
                            *size -= 8;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (f->header == OXM_OF_MPLS_TC){
                            fprintf(stream, "mpls_tc= %d", *f->value & 0x3);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (f->header == OXM_OF_METADATA || f->header == OXM_OF_METADATA_W){
                            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, ", ");
                }                                                                 
}
Ejemplo n.º 8
0
bool
match_std_nonstrict(struct ofl_match *a, struct ofl_match *b) {
  
struct ofl_match_tlv *flow_mod_match; 
    struct ofl_match_tlv *flow_entry_match;
    bool ret = false;

    /*Matches all flows */
    if(!a->header.length )
        return true;
    
    /* Loop through the match fields */
    HMAP_FOR_EACH(flow_mod_match, struct ofl_match_tlv, hmap_node, &a->match_fields){
       /* Check if the field is present in the flow entry */
        HMAP_FOR_EACH_WITH_HASH(flow_entry_match, struct ofl_match_tlv, hmap_node, hash_int(flow_mod_match->header, 0), &b->match_fields){                  
                int field_len =  OXM_LENGTH(flow_mod_match->header);
                bool has_mask;
                /* Check if both fields have or not a mask */
                if ( (OXM_HASMASK(flow_mod_match->header) && !OXM_HASMASK(flow_entry_match->header))
                    || (!OXM_HASMASK(flow_mod_match->header) && OXM_HASMASK(flow_entry_match->header))){
                    return false;
                }
                ret = true;
                has_mask = OXM_HASMASK(flow_mod_match->header);
                switch (field_len){
                    case (sizeof(uint8_t)):{
                        if (has_mask){
                            if (nonstrict_mask8(flow_mod_match->value, flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_8(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                        }
                        break;   
                    }
                    case (sizeof(uint16_t)):{ 
                        if (has_mask){
                            if (nonstrict_mask16(flow_mod_match->value,flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_16(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                        }
                        break;
                    } 
                    case (sizeof(uint32_t)):{ 
                        
                        if (has_mask){
                            if (nonstrict_mask32(flow_mod_match->value,flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len) ){
                              return false;
                            }
                        }
                        else 
                            if (matches_32(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                            }
                        break;
                    }
                    case (ETH_ADDR_LEN):{ 
                         if (has_mask){
                            if (nonstrict_ethaddr(flow_mod_match->value,flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len) == 0){
                              return false;
                            }
                         }
                        else 
                            if (eth_match(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                            }
                        break;
                    }
                    case (sizeof(uint64_t)):{ 
                        if (has_mask) {
                            if (nonstrict_mask64(flow_mod_match->value,flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_64(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                            }
                        break;
                    }
   		            case (16):{
                        if (has_mask){
                            if (nonstrict_ipv6(flow_mod_match->value,flow_entry_match->value + field_len, flow_entry_match->value,flow_entry_match->value + field_len)== 0){
                              return false;
                            }
                        }
                        else 
                            if (ipv6_match(flow_mod_match->value, flow_entry_match->value) == 0){
                              return false;
                            }
                        break;
                    }
 
            }
           
        }
         if (!ret)
            return ret;
        else ret = false;
    } 
    return true;

}
Ejemplo n.º 9
0
bool 
packet_match(struct ofl_match *flow_match, struct ofl_match *packet){

    struct ofl_match_tlv *f; 
    struct packet_fields *packet_f;
    bool ret = false;

    if (flow_match->header.length == 0){
        return true;
    }

    /* Loop through the match fields */
    HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &flow_match->match_fields){
        /* Check if the field is present in the packet */
        // HMAP_FOR_EACH_WITH_HASH(packet_f, struct packet_fields, hmap_node, hash_int(f->header, 0), &packet->match_fields){ 
        HMAP_FOR_EACH(packet_f, struct packet_fields, hmap_node, &packet->match_fields){ 
            if (OXM_TYPE(f->header) == OXM_TYPE(packet_f->header)) {
                int field_len =  OXM_LENGTH(f->header);
                bool has_mask = OXM_HASMASK(f->header);
                ret = true;
                if (has_mask)
                {
                    field_len = field_len/2;
                }
                switch (field_len){
                    case (sizeof(uint8_t)):{
                        if (has_mask){
                            if (pkt_mask8(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_8(f->value, packet_f->value) == 0){
                              return false;
                        }
                        break;   
                    }
                    case (sizeof(uint16_t)):{
                        if (OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_VLAN_VID)) {
                        	if (*((uint16_t*)f->value) == OFPVID_NONE)
                        		return false; // we have vlan tag when we expect none
                        	else if (*((uint16_t*)f->value) == OFPVID_PRESENT && has_mask)
                        		break; // this is the case where each vlan is a match
                        	else
                        		*((uint16_t*)f->value) &= VLAN_VID_MASK; // remove CFI bit
                        }

                        if (OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_IPV6_EXTHDR)){
                            if (ipv6_eh_match(f->value, packet_f->value) == 0) {
                                return false;
                            }
                        }
                        else if (has_mask){
                            if (pkt_mask16(f->value,f->value+ field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else {
                            if (pkt_match_16(f->value, packet_f->value) == 0){
                              return false;
                            }
                        }
                        break;
                    } 
                    case (sizeof(uint32_t)):{ 
                        if (has_mask){
                            if (OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_IPV4_DST) || OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_IPV4_SRC)
							    || OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_ARP_SPA) || OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_ARP_TPA)){
							    if (matches_mask32(f->value,f->value + field_len, packet_f->value) == 0){
                                     return false;
                                }
                            }     
                            else 
                                if (pkt_mask32(f->value,f->value + field_len, packet_f->value) == 0){
                                    return false;
                            }
                        }
                        else
                            if (OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_IPV4_DST) || OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_IPV4_SRC)
							    ||OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_ARP_SPA) || OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_ARP_TPA)){
							    if (matches_32(f->value, packet_f->value) == 0){
                                     return false;
                                }
                            }
                            else {
                                if (pkt_match_32(f->value, packet_f->value) == 0){
                                    return false;
                                }
                            }    
                        break;
                    }
                    case (ETH_ADDR_LEN):{ 
                         if (has_mask){
                            if (eth_mask(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                         }
                        else 
                            if (eth_match(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
                    case (sizeof(uint64_t)):{ 
                        if (has_mask) {
                            if (pkt_mask64(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_64(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
   		            case (16):{
                        if (has_mask){
                            if (ipv6_mask(f->value,f->value + field_len, packet_f->value) == 0){
                              
                              return false;
                            }
                        }
                        else 
                            if (ipv6_match(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
                } // end of switch case
            } // end of if (OXM_TYPE(f->header) == OXM_TYPE(packet_f->header))
        } // end of packet_match loop
        if (OXM_TYPE(f->header) == OXM_TYPE(OXM_OF_VLAN_VID))
        	if (*((uint16_t*)f->value) == OFPVID_NONE)
        		ret = true; // in case the packet has no vlan and this is what was expected

        if (!ret)
           return ret;
        else ret = false;
    } // end of flow_match loop

    return true;

}
Ejemplo n.º 10
0
bool
match_std_overlap(struct ofl_match *a, struct ofl_match *b)
{
    uint64_t all_mask[2] = {0, 0};
    struct ofl_match_tlv *f_a;
    struct ofl_match_tlv *f_b;
    int	header, header_m;
    int field_len;
    uint8_t *val_a, *mask_a;
    uint8_t *val_b, *mask_b;

    /* Loop through the match fields in flow entry a */
    HMAP_FOR_EACH(f_a, struct ofl_match_tlv, hmap_node, &a->match_fields)
    {
        field_len = OXM_LENGTH(f_a->header);
        val_a = f_a->value;
        if (OXM_HASMASK(f_a->header)) {
            field_len /= 2;
            header = (f_a->header & 0xfffffe00) | field_len;
            header_m = f_a->header;
            mask_a = f_a->value + field_len;
        } else {
            header = f_a->header;
            header_m = (f_a->header & 0xfffffe00) | 0x100 | (field_len << 1);
            /* Set a dummy mask with all bits set to 0 (valid) */
            mask_a = (uint8_t *) all_mask;
        }

        /* Check presence of corresponding match field in flow entry b
         * Need to check for both masked and non-masked field */
        f_b = oxm_match_lookup(header, b);
        if (!f_b) f_b = oxm_match_lookup(header_m, b);

        if (f_b) {
            val_b = f_b->value;
            if (OXM_HASMASK(f_b->header)) {
                mask_b = f_b->value + field_len;
            } else {
                /* Set a dummy mask with all bits set to 0 (valid) */
                mask_b = (uint8_t *) all_mask;
            }
            switch (field_len) {
            case 1:
                if (incompatible_8(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            case 2:
                if (incompatible_16(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            case 4:
                if (incompatible_32(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            case 6:
                if (incompatible_48(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            case 8:
                if (incompatible_64(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            case 16:
                if (incompatible_128(val_a, val_b, mask_a, mask_b)) {
                    return false;
                }
                break;
            default:
                /* Should never happen */
                break;
            } /* switch (field_len) */

        } /* if (f_b) */

    } /* HMAP_FOR_EACH */

    /* If we get here, none of the common match fields in a and b were found incompatible.
     * The flow entries overlap */
    return true;
}
Ejemplo n.º 11
0
/* Flow entry (a) matches flow entry (b) non-strictly if (a) matches whenever (b) matches.
 * Thus, flow (a) must not have more match fields than (b) and all match fields in (a) must
 * be equal or narrower in (b).
 * NOTE: Handling of bitmasked fields is not specified. In this implementation
 * a masked field of (a) matches the field of (b) if all masked bits of (b) are
 * also masked in (a), and for each unmasked bits of (b) , the bit is either
 * masked in (a), or is set to the same value in both matches.
 *
 */
bool
match_std_nonstrict(struct ofl_match *a, struct ofl_match *b)
{
    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;
    bool has_mask;

    /* Flow a is fully wildcarded */
    if (!a->header.length)
        return true;

    /* Loop through the match fields in flow entry a */
    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 */
        has_mask = OXM_HASMASK(flow_mod_match->header);
        field_len =  OXM_LENGTH(flow_mod_match->header);
        flow_mod_val = flow_mod_match->value;
        flow_entry_val = flow_entry_match->value;
        if (has_mask)
        {
            field_len /= 2;
            flow_mod_mask = flow_mod_match->value + field_len;
            flow_entry_mask = flow_entry_match->value + field_len;
        }
        switch (field_len) {
        case 1:
            if (has_mask) {
                if (!nonstrict_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 (!nonstrict_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 4:
            if (has_mask) {
                if (!nonstrict_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 (!nonstrict_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 (!nonstrict_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 (!nonstrict_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 a were equal or wider than the ones in b */
    /* It doesn't matter if there are further fields in b */
    return true;
}
Ejemplo n.º 12
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_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;
    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 */
        has_mask = OXM_HASMASK(flow_mod_match->header);
        field_len =  OXM_LENGTH(flow_mod_match->header);
        flow_mod_val = flow_mod_match->value;
        flow_entry_val = flow_entry_match->value;
        if (has_mask)
        {
            field_len /= 2;
            flow_mod_mask = flow_mod_match->value + field_len;
            flow_entry_mask = flow_entry_match->value + field_len;
        }
        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 4:
            if (has_mask) {
                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;
}
Ejemplo n.º 13
0
/* Returns true if the fields in *packet matches the flow entry in *flow_match */
bool
packet_match(struct ofl_match *flow_match, struct ofl_match *packet) {

    struct ofl_match_tlv *f;
    struct ofl_match_tlv *packet_f;
    bool has_mask;
    int field_len;
    int packet_header;
    uint8_t *flow_val, *flow_mask=0;
    uint8_t *packet_val;

    if (flow_match->header.length == 0) {
        return true;
    }

    /* Loop over the flow entry's match fields */
    HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &flow_match->match_fields)
    {
        /* Check presence of match field in packet */
        has_mask = OXM_HASMASK(f->header);
        field_len =  OXM_LENGTH(f->header);
        packet_header = f->header;
        flow_val = f->value;
        if (has_mask) {
            /* Clear the has_mask bit and divide the field_len by two in the packet field header */
            field_len /= 2;
            packet_header &= 0xfffffe00;
            packet_header |= field_len;
            flow_mask = f->value + field_len;
        }

        char *f_str = ofl_structs_oxm_tlv_to_string(f);
        free(f_str);

        /* Lookup the packet header */
        packet_f = oxm_match_lookup(packet_header, packet);
        if (!packet_f) {
            if (f->header==OXM_OF_VLAN_VID &&
                    *((uint16_t *) f->value)==OFPVID_NONE) {
                /* There is no VLAN tag, as required */
                continue;
            }
            return false;
        }

        /* Compare the flow and packet field values, considering the mask, if any */
        packet_val = packet_f->value;
        switch (field_len) {
        case 1:
            if (has_mask) {
                if (!match_mask8(flow_val, flow_mask, packet_val))
                    return false;
            }
            else {
                if (!match_8(flow_val, packet_val))
                    return false;
            }
            break;
        case 2:
            switch (packet_header) {
            case OXM_OF_VLAN_VID: {
                /* Special handling for VLAN ID */
                uint16_t flow_vlan_id = *((uint16_t *) flow_val);
                if (flow_vlan_id == OFPVID_NONE) {
                    /* Packet has a VLAN tag when none should be there */
                    return false;
                } else if (flow_vlan_id == OFPVID_PRESENT) {
                    /* Any VLAN ID is acceptable. No further checks */
                } else {
                    /* Check the VLAN ID */
                    if (!match_16(flow_val, packet_val))
                        return false;
                }
                break;
            }
            case OXM_OF_IPV6_EXTHDR: {
                /* Special handling for IPv6 Extension header */
                uint16_t flow_eh = *((uint16_t *) flow_val);
                uint16_t packet_eh = *((uint16_t *) packet_val);
                if ((flow_eh & packet_eh) != flow_eh) {
                    /* The packet doesn't have all extension headers specified in the flow */
                    return false;
                }
                break;
            }
            default:
                if (has_mask) {
                    if (!match_mask16(flow_val, flow_mask, packet_val))
                        return false;
                }
                else {
                    if (!match_16(flow_val, packet_val))
                        return false;
                }
                break;
            }
            break;
        case 4:
            if (has_mask) {
                if (!match_mask32(flow_val, flow_mask, packet_val))
                    return false;
            }
            else {
                if (!match_32(flow_val, packet_val))
                    return false;
            }
            break;
        case 6:
            if (has_mask) {
                if (!match_mask48(flow_val, flow_mask, packet_val))
                    return false;
            }
            else {
                if (!match_48(flow_val, packet_val))
                    return false;
            }
            break;
        case 8:
            if (has_mask) {
                if (!match_mask64(flow_val, flow_mask, packet_val))
                    return false;
            }
            else {
                if (!match_64(flow_val, packet_val))
                    return false;
            }
            break;
        case 16:
            if (has_mask) {
                if (!match_mask128(flow_val, flow_mask, packet_val))
                    return false;
            }
            else {
                if (!match_128(flow_val, packet_val))
                    return false;
            }
            break;
        default:
            /* Should never happen */
            break;
        }
    }
    /* If we get here, all match fields in the flow entry matched the packet */
    return true;
}
Ejemplo n.º 14
0
bool 
packet_match(struct ofl_match *flow_match, struct ofl_match *packet){

    struct ofl_match_tlv *f; 
    struct packet_fields *packet_f;
    bool ret = false;

    if (flow_match->header.length == 0){
        return true;
    }
    /*TODO: Possible combinations of VLAN_ID and masks */
    HMAP_FOR_EACH_WITH_HASH(f, struct ofl_match_tlv, hmap_node,hash_int(OXM_OF_VLAN_VID, 0), &flow_match->match_fields){
        uint16_t *matchv = (uint16_t*) f->value;
        /* Check if the field is present in the packet */
        HMAP_FOR_EACH_WITH_HASH(packet_f, struct packet_fields, hmap_node, hash_int(OXM_OF_VLAN_VID, 0), &packet->match_fields){     
            /* Do not match packets with a VLAN Tag */
            if (*matchv == OFPVID_NONE && !OXM_HASMASK(f->header))
                return false;
            ret = true;
        }

        if ((*matchv == OFPVID_PRESENT)  & (OXM_HASMASK(f->header))){
            uint16_t *maskv = (uint16_t*) f->value + 2;
                if (*maskv == OFPVID_PRESENT && !ret )
                    return false;     
        }
          
    }      

    /* Loop through the match fields */
    HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &flow_match->match_fields){
        /* Check if the field is present in the packet */
        HMAP_FOR_EACH_WITH_HASH(packet_f, struct packet_fields, hmap_node, hash_int(f->header, 0), &packet->match_fields){ 
                int field_len =  OXM_LENGTH(f->header);
                bool has_mask = OXM_HASMASK(f->header);
                ret = true;
                switch (field_len){
                    case (sizeof(uint8_t)):{
                        if (has_mask){
                            if (pkt_mask8(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_8(f->value, packet_f->value) == 0){
                              return false;
                        }
                        break;   
                    }
                    case (sizeof(uint16_t)):{
                        if (has_mask){
                            if (pkt_mask16(f->value,f->value+ field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else {
                            if (pkt_match_16(f->value, packet_f->value) == 0){
                              return false;
                            }
                        }
                        break;
                    } 
                    case (sizeof(uint32_t)):{ 
                        if (has_mask){
                            if (f->header == OXM_OF_IPV4_DST || f->header == OXM_OF_IPV4_SRC
							    ||f->header == OXM_OF_ARP_SPA || f->header == OXM_OF_ARP_TPA){
							    if (matches_mask32(f->value,f->value + field_len, packet_f->value) == 0){
                                     return false;
                                }
                            }     
                            else 
                                if (pkt_mask32(f->value,f->value + field_len, packet_f->value) == 0){
                                    return false;
                            }
                        }
                        else
                            if (f->header == OXM_OF_IPV4_DST || f->header == OXM_OF_IPV4_SRC
							    ||f->header == OXM_OF_ARP_SPA || f->header == OXM_OF_ARP_TPA){
							    if (matches_32(f->value, packet_f->value) == 0){
                                     return false;
                                }
                            }
                            
                            else 
                                if (pkt_match_32(f->value, packet_f->value) == 0){
                                    return false;
                            }
                        break;
                    }
                    case (ETH_ADDR_LEN):{ 
                         if (has_mask){
                            if (eth_mask(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                         }
                        else 
                            if (eth_match(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
                    case (sizeof(uint64_t)):{ 
                        if (has_mask) {
                            if (pkt_mask64(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else 
                            if (matches_64(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
   		            case (16):{
                        if (has_mask){
                            if (ipv6_mask(f->value,f->value + field_len, packet_f->value) == 0){
                              return false;
                            }
                        }
                        else 
                            if (ipv6_match(f->value, packet_f->value) == 0){
                              return false;
                            }
                        break;
                    }
               
            }
        }
         if (!ret)
            return ret;
         else ret = false;      
    }

    return true;

}
Ejemplo n.º 15
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, ", ");
                }                 
                                
}