Example #1
0
void
construct_ofp_match( struct ofp_match *match, const oxm_matches *matches ) {
  assert( match != NULL );

  uint16_t oxm_len = 0;
  uint16_t oxms_len = 0;
  uint16_t ofp_match_len = 0;
  uint16_t pad_len = 0;
  oxm_match_header *dst, *src;

  if ( matches != NULL ) {
    uint16_t offset = offsetof( struct ofp_match, oxm_fields );
    dst = ( oxm_match_header * ) ( ( char * ) match + offset );

    list_element *elem = matches->list;
    while ( elem != NULL ) {
      src = ( oxm_match_header * ) elem->data;
      hton_oxm_match( dst, src );

      oxm_len = ( uint16_t ) ( sizeof( oxm_match_header ) + OXM_LENGTH( *src ) );
      oxms_len = ( uint16_t ) ( oxms_len + oxm_len );
      dst = ( oxm_match_header * ) ( ( char * ) dst + oxm_len );
      elem = elem->next;
    }
  }
Example #2
0
VALUE
ofp_match_to_r_match( const struct ofp_match *match ) {
  assert( match != NULL );
  assert( match->length >= offsetof( struct ofp_match, oxm_fields ) );

  uint16_t oxms_len = 0;
  uint16_t oxm_len = 0;
  const oxm_match_header *src;

  uint16_t offset = offsetof( struct ofp_match, oxm_fields );
  oxms_len = ( uint16_t ) ( match->length - offset );
  src = ( const oxm_match_header * ) ( ( const char * ) match + offset );
  VALUE r_attributes = rb_hash_new();

  while ( oxms_len > sizeof( oxm_match_header ) ) {
    oxm_len = OXM_LENGTH( *src );
    unpack_r_match( src, r_attributes );

    offset = ( uint16_t ) ( sizeof( oxm_match_header ) + oxm_len );
    if ( oxms_len < offset ) {
      break;
    }
    oxms_len = ( uint16_t ) ( oxms_len - offset );
    src = ( const oxm_match_header * ) ( ( const char * ) src + offset );
  }
  return rb_funcall( rb_eval_string( "Trema::Match" ), rb_intern( "new" ), 1, r_attributes );
}
Example #3
0
oxm_matches *
parse_ofp_match( struct ofp_match *match ) {
  assert( match != NULL );
  assert( ntohs( match->length ) >= offsetof( struct ofp_match, oxm_fields ) );

  uint16_t oxms_len = 0;
  uint16_t oxm_len = 0;
  oxm_match_header *dst, *src;
  oxm_matches *matches = create_oxm_matches();

  uint16_t offset = offsetof( struct ofp_match, oxm_fields );
  oxms_len = ( uint16_t ) ( ntohs( match->length ) - offset );
  src = ( oxm_match_header * ) ( ( char * ) match + offset );

  while ( oxms_len > sizeof( oxm_match_header ) ) {
    oxm_len = OXM_LENGTH( ntohl( *src ) );
    dst = ( oxm_match_header * ) xcalloc( 1, sizeof( oxm_match_header ) + oxm_len );
    ntoh_oxm_match( dst, src );

    append_oxm_match( matches, dst );

    offset = ( uint16_t ) ( sizeof( oxm_match_header ) + oxm_len );
    if ( oxms_len < offset ) {
      break;
    }
    oxms_len = ( uint16_t ) ( oxms_len - offset );
    src = ( oxm_match_header * ) ( ( char * ) src + offset );
  }

  return matches;
}
Example #4
0
static flow_stats *
retrieve_flow_stats( uint32_t *nr_stats, const uint8_t table_id, const uint32_t out_port, const uint32_t out_group,
                     const uint64_t cookie, const uint64_t cookie_mask, const struct ofp_match *ofp_match ) {
  match *flow_match = create_match();
  size_t match_len = 0;
  if ( ofp_match != NULL ) {
    match_len = ofp_match->length - offsetof( struct ofp_match, oxm_fields );
    // translate the ofp_match to datapath match.
    const oxm_match_header *hdr = ( const oxm_match_header * ) ofp_match->oxm_fields;
    while ( match_len > 0 ) {
      assign_match( flow_match, hdr );
      match_len -= ( sizeof( *hdr ) + OXM_LENGTH( *hdr ) );
      if ( match_len > 0 ) {
        hdr = ( const oxm_match_header * ) ( ( const char * ) hdr + sizeof( *hdr ) + OXM_LENGTH( *hdr ) );
      }
    }
  }
static void
test_retrieve_flow_stats( void **state ) {
  UNUSED( state );

  uint16_t total_len = ( uint16_t ) ( sizeof( struct ofp_match ) +
    OXM_LENGTH( OXM_OF_IN_PORT ) +
    sizeof( uint32_t ) + OXM_LENGTH( OXM_OF_IN_PHY_PORT ) + 
    sizeof( uint32_t ) + OXM_LENGTH ( OXM_OF_METADATA )
  );
  total_len = ( uint16_t ) ( total_len + PADLEN_TO_64( total_len ) );
  struct ofp_match *ofp_match =  ( struct ofp_match * ) ( xmalloc( total_len ) );
  ofp_match->type = OFPMT_OXM;
  ofp_match->length = total_len;

  uint32_t *oxm_id = ( uint32_t * ) ( ( char * ) ofp_match->oxm_fields );
  *oxm_id = OXM_OF_IN_PORT;

  uint32_t *in_port = ( uint32_t * ) ( ( char * ) oxm_id + sizeof( *oxm_id ) );
  *in_port = PORT_NO;

  oxm_id = ( uint32_t * ) ( ( char * ) in_port + OXM_LENGTH( OXM_OF_IN_PORT ) );
  *oxm_id = OXM_OF_IN_PHY_PORT;

  uint32_t *in_phy_port = ( uint32_t * ) ( ( char * ) oxm_id + sizeof( *oxm_id ) );
  *in_phy_port = PORT_NO;

  oxm_id = ( uint32_t * ) ( ( char * ) in_phy_port + OXM_LENGTH( OXM_OF_IN_PHY_PORT ) );
  *oxm_id = OXM_OF_METADATA;

  uint64_t *metadata = ( uint64_t * ) ( ( char * ) oxm_id + sizeof( *oxm_id ) );
  uint64_t dummy_metadata = 0x1122334455667788;
  memcpy( metadata, &dummy_metadata, sizeof( uint64_t ) );
  
  uint32_t nr_stats = 0;
  uint8_t table_id = TABLE_ID;
  uint32_t out_port = PORT_NO;
  uint32_t out_group = GROUP_ID;
  uint64_t cookie = COOKIE;
  uint64_t cookie_mask = 0xffffffffffffffff;
  init_table_manager();
  retrieve_flow_stats( &nr_stats, table_id, out_port, out_group, cookie, cookie_mask, ofp_match );
  assert_int_equal( nr_stats, 0 );
}
Example #6
0
static bool
append_oxm_match_eth_addr( oxm_matches *matches, oxm_match_header header, uint8_t addr[ OFP_ETH_ALEN ] ) {
  assert( matches != NULL );
  assert( OXM_LENGTH( header ) == ( OFP_ETH_ALEN * sizeof( uint8_t ) ) );

  oxm_match_header *buf = xmalloc( sizeof( oxm_match_header ) + ( OFP_ETH_ALEN * sizeof( uint8_t ) ) );
  *buf = header;
  uint8_t *value = ( uint8_t * ) ( ( char * ) buf + sizeof( oxm_match_header ) );
  memcpy( value, addr, OFP_ETH_ALEN * sizeof( uint8_t ) );

  return append_oxm_match( matches, buf );
}
Example #7
0
static bool
append_oxm_match_64( oxm_matches *matches, oxm_match_header header, uint64_t value ) {
  assert( matches != NULL );
  assert( OXM_LENGTH( header ) == sizeof( uint64_t ) );

  oxm_match_header *buf = xmalloc( sizeof( oxm_match_header ) + sizeof( uint64_t ) );
  *buf = header;
  uint64_t *v = ( uint64_t * ) ( ( char * ) buf + sizeof( oxm_match_header ) );
  *v = value;

  return append_oxm_match( matches, buf );
}
void ofl_structs_match_convert_pktf2oflm(struct hmap * hmap_packet_fields, struct hmap * hmap_ofl_match)
/*
* Used to convert between a hmap of "struct packet_fields" to "struct ofl_match"
*/
{
    struct packet_fields *iter;
    
    HMAP_FOR_EACH(iter,struct packet_fields, hmap_node, hmap_packet_fields)
    {
        struct ofl_match_tlv * new_entry = (struct ofl_match_tlv *) malloc(sizeof(struct ofl_match_tlv));
        
        new_entry->header = iter->header;
        new_entry->value = (uint8_t *) malloc(OXM_LENGTH(new_entry->header));
        
        memcpy(new_entry->value, iter->value,OXM_LENGTH(new_entry->header));
        
        hmap_insert_fast(hmap_ofl_match, &new_entry->hmap_node,
        hash_int(new_entry->header, 0));
    }

}
Example #9
0
static bool
append_oxm_match_32w( oxm_matches *matches, oxm_match_header header, uint32_t value, uint32_t mask ) {
  assert( matches != NULL );
  assert( OXM_LENGTH( header ) == ( sizeof( uint32_t ) * 2 ) );

  oxm_match_header *buf = xmalloc( sizeof( oxm_match_header ) + sizeof( uint32_t ) * 2 );
  *buf = header;
  uint32_t *v = ( uint32_t * ) ( ( char * ) buf + sizeof( oxm_match_header ) );
  *v = value;
  v = ( uint32_t * ) ( ( char * ) v + sizeof( uint32_t ) );
  *v = mask;

  return append_oxm_match( matches, buf );
}
Example #10
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 );
}
Example #11
0
size_t
ofl_actions_ofp_len(struct ofl_action_header *action, struct ofl_exp *exp) {
    switch (action->type) {
        case OFPAT_OUTPUT:
            return sizeof(struct ofp_action_output);
       
        case OFPAT_COPY_TTL_OUT:
        case OFPAT_COPY_TTL_IN:
            return sizeof(struct ofp_action_header);
        case OFPAT_SET_MPLS_TTL:
            return sizeof(struct ofp_action_mpls_ttl);
        case OFPAT_DEC_MPLS_TTL:
            return sizeof(struct ofp_action_header);
        case OFPAT_PUSH_VLAN:
        case OFPAT_PUSH_PBB:
        case OFPAT_PUSH_MPLS:  
            return sizeof(struct ofp_action_push);
        case OFPAT_POP_VLAN:
        case OFPAT_POP_PBB:
            return sizeof(struct ofp_action_header);
        case OFPAT_POP_MPLS:
            return sizeof(struct ofp_action_pop_mpls);
        case OFPAT_SET_QUEUE:
            return sizeof(struct ofp_action_set_queue);
        case OFPAT_GROUP:
            return sizeof(struct ofp_action_group);
        case OFPAT_SET_NW_TTL:
            return sizeof(struct ofp_action_nw_ttl);
        case OFPAT_DEC_NW_TTL:
            return sizeof(struct ofp_action_header);
        case OFPAT_SET_FIELD: {
            struct ofl_action_set_field  *a = (struct ofl_action_set_field  *) action;  
            return sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(a->field->header),8) ;
        }    
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->ofp_len == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "requesting experimenter length, but no callback was given.");
                return -1;
            }
            return exp->act->ofp_len(action);
        }
        default:
            return 0;
    }
}
Example #12
0
uint16_t
get_oxm_matches_length( const oxm_matches *matches ) {
  debug( "Calculating the total length of matches." );

  int length = 0;
  if ( matches != NULL ) {
    list_element *match = matches->list;
    while ( match != NULL ) {
      oxm_match_header *header = match->data;
      length += ( int ) ( ( uint8_t ) OXM_LENGTH( *header ) + sizeof( oxm_match_header ) );
      match = match->next;
    }
  }

  debug( "Total length of matches = %d.", length );

  assert( length <= UINT16_MAX );

  return ( uint16_t ) length;
}
Example #13
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;
}
Example #14
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;
}
Example #15
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;
}
Example #16
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;
}
Example #17
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;
}
ofl_err
ofl_actions_unpack(struct ofp_action_header *src, size_t *len, struct ofl_action_header **dst, struct ofl_exp *exp) {

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

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

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

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

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

            sa = (struct ofp_action_output *)src;

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

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

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

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

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

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

            sa = (struct ofp_action_mpls_ttl *)src;

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

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

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

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

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

            sa = (struct ofp_action_push *)src;

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

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

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

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

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

            sa = (struct ofp_action_pop_mpls *)src;

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

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

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

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

            sa = (struct ofp_action_set_queue *)src;

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

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

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

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

            sa = (struct ofp_action_group *)src;

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

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

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

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

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

            sa = (struct ofp_action_nw_ttl *)src;

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

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

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

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

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

        case OFPAT_EXPERIMENTER: {
            ofl_err error;

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

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

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

    return 0;
}
Example #19
0
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act ) 
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        struct packet_fields *iter;
        /* Search field on the description of the packet. */
        HMAP_FOR_EACH_WITH_HASH(iter,struct packet_fields, hmap_node, hash_int(act->field->header,0), &pkt->handle_std->match.match_fields)
        {
            /* TODO: Checksum for SCTP and ICMP */
            if (iter->header == OXM_OF_IPV4_SRC || iter->header == OXM_OF_IPV4_DST 
                || iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
            {
                uint16_t *aux_old ;
                aux_old = (uint16_t *)malloc(sizeof(uint16_t));
                memcpy(aux_old, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                if (iter->header == OXM_OF_IP_DSCP)
                {
                    uint8_t* aux;
                    aux = (uint8_t *)malloc(OXM_LENGTH(iter->header));
                    memcpy(aux,((uint8_t*)pkt->buffer->data + iter->pos) , OXM_LENGTH(iter->header));
                    *aux = *aux ^ ((*act->field->value) << 2 );
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , aux , OXM_LENGTH(iter->header));
                    free(aux);
                }
                else if (iter->header == OXM_OF_IP_ECN)
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                else 
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                
                // update TCP/UDP checksum
                struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;
                if (pkt->handle_std->proto->tcp != NULL) {
                    struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_src,htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_dst,htonl(*((uint32_t*) act->field->value)));
                    }
                } else if (pkt->handle_std->proto->udp != NULL) {
                    struct udp_header *udp = pkt->handle_std->proto->udp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                    }
                }
                if (iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
                {
                    uint16_t *aux ;
                    aux = (uint16_t *)malloc(sizeof(uint16_t));
                    memcpy(aux, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                    ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, *aux_old, *aux);
                    free(aux);
                }
                else if (iter->header == OXM_OF_IPV4_SRC)
                {
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                }
                else 
                { 
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                }  
                pkt->handle_std->valid = false;
                packet_handle_std_validate(pkt->handle_std);
                free(aux_old);
                return;        	       
            }
            if (iter->header == OXM_OF_TCP_SRC)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_TCP_DST)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_SRC)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_DST)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, htons(*((uint16_t*) act->field->value)));
            }
            if (iter->header == OXM_OF_IPV6_SRC || iter->header == OXM_OF_IPV6_DST || 
                iter->header == OXM_OF_ETH_SRC || iter->header == OXM_OF_ETH_DST   ||
                iter->header == OXM_OF_ARP_SPA || iter->header == OXM_OF_ARP_TPA   ||
                iter->header == OXM_OF_ARP_SHA || iter->header == OXM_OF_ARP_THA)
            {
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            /* Found the field, lets re-write it!! */
    	    uint8_t* tmp = (uint8_t*) malloc(OXM_LENGTH(iter->header));
    	    uint8_t i;
    	    for (i=0;i<OXM_LENGTH(iter->header);i++)
    	    {
        	    memcpy(((uint8_t*)tmp + i) , (act->field->value + OXM_LENGTH(iter->header) - i -1 ), 1); 
    	    }  
    	    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , tmp , OXM_LENGTH(iter->header));
            pkt->handle_std->valid = false;
    	    return;
        }
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_FIELD action on packet with no corresponding field.");
    }

}
Example #20
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;

}
Example #21
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;

}
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act ) 
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        struct packet_fields *iter;
        /* Search field on the description of the packet. */
        HMAP_FOR_EACH_WITH_HASH(iter,struct packet_fields, hmap_node, hash_int(act->field->header,0), &pkt->handle_std->match.match_fields)
        {
            struct ip_header *ipv4;
            struct mpls_header *mpls;
            struct vlan_header *vlan;
            uint8_t* tmp;
            size_t i;
            
            /* TODO: Checksum for SCTP and ICMP */
            if (iter->header == OXM_OF_IPV4_SRC || iter->header == OXM_OF_IPV4_DST 
                || iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
            {
                uint16_t *aux_old ;
                aux_old = (uint16_t *)malloc(sizeof(uint16_t));
                memcpy(aux_old, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                if (iter->header == OXM_OF_IP_DSCP)
                {
                    uint8_t* aux;
                    aux = (uint8_t *)malloc(OXM_LENGTH(iter->header));
                    memcpy(aux,((uint8_t*)pkt->buffer->data + iter->pos) , OXM_LENGTH(iter->header));
                    *aux = *aux ^ ((*act->field->value) << 2 );
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , aux , OXM_LENGTH(iter->header));
                    free(aux);
                }
                else if (iter->header == OXM_OF_IP_ECN)
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                else 
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }

                // update TCP/UDP checksum
                ipv4 = pkt->handle_std->proto->ipv4;
                if (pkt->handle_std->proto->tcp != NULL) {
                    struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_src,htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_dst,htonl(*((uint32_t*) act->field->value)));
                    }
                } else if (pkt->handle_std->proto->udp != NULL) {
                    struct udp_header *udp = pkt->handle_std->proto->udp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                    }
                }

                if (iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
                {
                    uint16_t *aux ;
                    aux = (uint16_t *)malloc(sizeof(uint16_t));
                    memcpy(aux, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                    ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, *aux_old, *aux);
                    free(aux);
                }
                else if (iter->header == OXM_OF_IPV4_SRC)
                {
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                }
                else 
                { 
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                }  
                pkt->handle_std->valid = false;
                packet_handle_std_validate(pkt->handle_std);
                free(aux_old);
                return;        	       
            }
            if (iter->header == OXM_OF_TCP_SRC)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_TCP_DST)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_SRC)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_DST)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, htons(*((uint16_t*) act->field->value)));
            }
            if (iter->header == OXM_OF_IPV6_SRC || iter->header == OXM_OF_IPV6_DST || 
                iter->header == OXM_OF_ETH_SRC || iter->header == OXM_OF_ETH_DST   ||
                iter->header == OXM_OF_ARP_SPA || iter->header == OXM_OF_ARP_TPA   ||
                iter->header == OXM_OF_ARP_SHA || iter->header == OXM_OF_ARP_THA) {
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            if (iter->header == OXM_OF_VLAN_VID){
                uint16_t vlan_id =  *((uint16_t*) act->field->value);
                vlan = pkt->handle_std->proto->vlan;
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_VID_MASK) | (vlan_id & VLAN_VID_MASK));
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &vlan->vlan_tci , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }            
            if (iter->header == OXM_OF_VLAN_PCP){
                uint8_t vlan_pcp =  *((uint8_t*) act->field->value);
                vlan = pkt->handle_std->proto->vlan;
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_PCP_MASK) | ((vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK));
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &vlan->vlan_tci , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            if (iter->header == OXM_OF_MPLS_LABEL){
                    uint32_t mpls_label =  *((uint32_t*) act->field->value);
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_LABEL_MASK)) | ntohl((mpls_label << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;
            }
            if (iter->header == OXM_OF_MPLS_TC){
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_TC_MASK)) | ntohl((*act->field->value << MPLS_TC_SHIFT) & MPLS_TC_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;
            }
            if (iter->header == OXM_OF_MPLS_BOS){
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_S_MASK)) | ntohl((*act->field->value << MPLS_S_SHIFT) & MPLS_S_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;             
            }
            tmp = (uint8_t*) malloc(OXM_LENGTH(iter->header));
    	    for (i=0;i<OXM_LENGTH(iter->header);i++)
    	    {
        	    memcpy(((uint8_t*)tmp + i) , (act->field->value + OXM_LENGTH(iter->header) - i -1 ), 1); 
    	    }
    	    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , tmp , OXM_LENGTH(iter->header));
            pkt->handle_std->valid = false;
    	    return;
        }
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_FIELD action on packet with no corresponding field.");
    }

}
Example #23
0
size_t
ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data,  struct ofl_exp *exp) {

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

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

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

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

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

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

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

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

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

            da->len =    htons(sizeof(struct ofp_action_nw_ttl));
            da->nw_ttl = htons(sa->nw_ttl);
            memset(da->pad, 0x00, 3);
            return sizeof(struct ofp_action_nw_ttl);
        }
        case OFPAT_DEC_NW_TTL: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
        case OFPAT_SET_FIELD: {
            struct ofl_action_set_field *sa = (struct ofl_action_set_field *) src;
            struct ofp_action_set_field *da = (struct ofp_action_set_field *) dst;
            uint32_t header;
            uint8_t padding_size;
                        
            da->len = htons(sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(sa->field->header),8));
            /*Put OXM header in the field*/
            header = htonl(sa->field->header);
            memcpy(&da->field, &header, 4);
            switch (OXM_LENGTH(sa->field->header)){
                case 1:
                case 6:
                case 16:
                    memcpy(data + (sizeof(struct ofp_action_set_field)), sa->field->value,OXM_LENGTH(sa->field->header));
                    break;
                
                case 2:{
                   uint16_t value = htons(*((uint16_t*) sa->field->value));
                   memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
                case 4:{
                    uint32_t value = htons(*((uint32_t*) sa->field->value));
                    memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
                case 8:{
                    uint64_t value = htons(*((uint64_t*) sa->field->value));
                    memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
            }
            /*padding*/
            padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header);
            memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size);            
            return ntohs((da->len));
        
        }
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given.");
                return 0;
            }
            return exp->act->pack(src, dst);
        }
        default:
            return 0;
    };
}
Example #24
0
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act )
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        /*Field existence is guaranteed by the
        field pre-requisite on matching */
        switch(act->field->header) {
        case OXM_OF_ETH_DST: {
            memcpy(pkt->handle_std->proto->eth->eth_dst,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ETH_SRC: {
            memcpy(pkt->handle_std->proto->eth->eth_src,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ETH_TYPE: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->eth->eth_type,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_VLAN_VID: {
            struct vlan_header *vlan =  pkt->handle_std->proto->vlan;
            /* VLAN existence is no guaranteed by match prerquisite*/
            if(vlan != NULL) {
                uint16_t v = (*(uint16_t*)act->field->value);
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_VID_MASK)
                                       | (v & VLAN_VID_MASK));

            }
            break;
        }
        case OXM_OF_VLAN_PCP: {
            struct vlan_header *vlan = pkt->handle_std->proto->vlan;
            /* VLAN existence is no guaranteed by match prerquisite*/
            if(vlan != NULL) {
                vlan->vlan_tci = (vlan->vlan_tci & ~htons(VLAN_PCP_MASK))
                                 | htons(*act->field->value << VLAN_PCP_SHIFT);
                break;
            }
        }
        case OXM_OF_IP_DSCP: {
            struct ip_header *ipv4 =  pkt->handle_std->proto->ipv4;
            uint8_t tos = (ipv4->ip_tos & ~IP_DSCP_MASK) |
                          (*act->field->value << 2);

            ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, (uint16_t)
                                          (ipv4->ip_tos), (uint16_t)tos);
            ipv4->ip_tos = tos;
            break;
        }
        case OXM_OF_IP_ECN: {
            struct ip_header *ipv4 =  pkt->handle_std->proto->ipv4;
            uint8_t tos = (ipv4->ip_tos & ~IP_ECN_MASK) |
                          (*act->field->value & IP_ECN_MASK);
            ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, (uint16_t)
                                          (ipv4->ip_tos), (uint16_t)tos);
            ipv4->ip_tos = tos;
            break;
        }
        case OXM_OF_IP_PROTO: {
            pkt->handle_std->proto->ipv4->ip_proto = *act->field->value;
            break;
        }
        case OXM_OF_IPV4_SRC: {
            struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;

            /*Reconstruct TCP or UDP checksum*/
            if (pkt->handle_std->proto->tcp != NULL) {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum32(tcp->tcp_csum,
                                              ipv4->ip_src, *((uint32_t*) act->field->value));
            } else if (pkt->handle_std->proto->udp != NULL) {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum32(udp->udp_csum,
                                              ipv4->ip_src, *((uint32_t*) act->field->value));
            }

            ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src,
                                          *((uint32_t*) act->field->value));

            ipv4->ip_src = *((uint32_t*) act->field->value);
            break;
        }
        case OXM_OF_IPV4_DST: {
            struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;

            /*Reconstruct TCP or UDP checksum*/
            if (pkt->handle_std->proto->tcp != NULL) {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum32(tcp->tcp_csum,
                                              ipv4->ip_dst, *((uint32_t*) act->field->value));
            } else if (pkt->handle_std->proto->udp != NULL) {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum32(udp->udp_csum,
                                              ipv4->ip_dst, *((uint32_t*) act->field->value));
            }

            ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst,
                                          *((uint32_t*) act->field->value));

            ipv4->ip_dst = *((uint32_t*) act->field->value);
            break;
        }
        case OXM_OF_TCP_SRC: {
            struct tcp_header *tcp = pkt->handle_std->proto->tcp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src,*v);
            memcpy(&tcp->tcp_src, v, OXM_LENGTH(act->field->header));

            break;
        }
        case OXM_OF_TCP_DST: {
            struct tcp_header *tcp = pkt->handle_std->proto->tcp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst,*v);
            memcpy(&tcp->tcp_dst, v, OXM_LENGTH(act->field->header));

            break;
        }
        case OXM_OF_UDP_SRC: {
            struct udp_header *udp = pkt->handle_std->proto->udp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, *v);
            memcpy(&udp->udp_src, v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_UDP_DST: {
            struct udp_header *udp = pkt->handle_std->proto->udp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, *v);
            memcpy(&udp->udp_dst, v, OXM_LENGTH(act->field->header));
            break;
        }
        /*TODO recalculate SCTP checksum*/
        case OXM_OF_SCTP_SRC: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->sctp->sctp_src,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_SCTP_DST: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->sctp->sctp_dst,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ICMPV4_TYPE:
        case OXM_OF_ICMPV6_TYPE: {
            pkt->handle_std->proto->icmp->icmp_type = *act->field->value;
            break;
        }

        case OXM_OF_ICMPV4_CODE:
        case OXM_OF_ICMPV6_CODE: {
            pkt->handle_std->proto->icmp->icmp_code = *act->field->value;
            break;
        }
        case OXM_OF_ARP_OP: {
            pkt->handle_std->proto->arp->ar_op = htons(*((uint16_t*) act->field->value));
            break;
        }
        case OXM_OF_ARP_SPA: {
            pkt->handle_std->proto->arp->ar_spa = *((uint32_t*)
                                                    act->field->value);
            break;
        }
        case OXM_OF_ARP_TPA: {
            pkt->handle_std->proto->arp->ar_tpa = *((uint32_t*)
                                                    act->field->value);
            break;
        }
        case OXM_OF_ARP_SHA: {
            memcpy(pkt->handle_std->proto->arp->ar_sha,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ARP_THA: {
            memcpy(pkt->handle_std->proto->arp->ar_tha,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_SRC: {
            memcpy(&pkt->handle_std->proto->ipv6->ipv6_src,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_DST: {
            memcpy(&pkt->handle_std->proto->ipv6->ipv6_dst,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_FLABEL: {
            struct ipv6_header *ipv6 = (struct ipv6_header*)
                                       pkt->handle_std->proto->ipv6;
            uint32_t v = *((uint32_t*) act->field->value);
            ipv6->ipv6_ver_tc_fl  = (ipv6->ipv6_ver_tc_fl  &
                                     ~ntohl(IPV6_FLABEL_MASK)) | ntohl(v & IPV6_FLABEL_MASK);
            break;
        }
        /*IPV6 Neighbor Discovery */
        case OXM_OF_IPV6_ND_TARGET: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            uint8_t *data = (uint8_t*)icmp;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct icmp_header) + 4;

            memcpy(data + offset, act->field->value,
                   OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_ND_SLL: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            struct ipv6_nd_options_hd *opt = (struct ipv6_nd_options_hd*)
                                             icmp + sizeof(struct icmp_header);
            uint8_t *data = (uint8_t*) opt;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct ipv6_nd_header);

            if(opt->type == ND_OPT_SLL) {
                memcpy(data + offset, act->field->value,
                       OXM_LENGTH(act->field->header));
            }
            break;
        }
        case OXM_OF_IPV6_ND_TLL: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            struct ipv6_nd_options_hd *opt = (struct ipv6_nd_options_hd*)
                                             icmp + sizeof(struct icmp_header);
            uint8_t *data = (uint8_t*) opt;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct ipv6_nd_header);

            if(opt->type == ND_OPT_TLL) {
                memcpy(data + offset, act->field->value,
                       OXM_LENGTH(act->field->header));
            }
            break;
        }
        case OXM_OF_MPLS_LABEL: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            uint32_t v = *((uint32_t*) act->field->value);
            mpls->fields = (mpls->fields & ~ntohl(MPLS_LABEL_MASK)) |
                           ntohl((v << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK);
            break;
        }
        case OXM_OF_MPLS_TC: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            mpls->fields = (mpls->fields & ~ntohl(MPLS_TC_MASK))
                           | ntohl((*act->field->value << MPLS_TC_SHIFT) & MPLS_TC_MASK);
            break;
        }
        case OXM_OF_MPLS_BOS: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            mpls->fields = (mpls->fields & ~ntohl(MPLS_S_MASK))
                           | ntohl((*act->field->value << MPLS_S_SHIFT) & MPLS_S_MASK);
            break;
        }
        case OXM_OF_PBB_ISID : {
            struct pbb_header *pbb = pkt->handle_std->proto->pbb;
            uint32_t v = *((uint32_t*) act->field->value);
            pbb->id = (pbb->id & ~ntohl(PBB_ISID_MASK)) |
                      ntohl(v & PBB_ISID_MASK);
            break;
        }
        default:
            VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to set unknow field.");
            break;
        }
        pkt->handle_std->valid = false;
        return;
    }

}
Example #25
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;
}
Example #26
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;

}
size_t
ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data,  struct ofl_exp *exp) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        }
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given.");
                return 0;
            }
            return exp->act->pack(src, dst);
        }
        default:
            return 0;
    };
Example #28
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;
}
Example #29
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;
}
void
ofl_action_print(FILE *stream, struct ofl_action_header *act, struct ofl_exp *exp) {

    ofl_action_type_print(stream, act->type);

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

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

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

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

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

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

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

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

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

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