示例#1
0
static void
handle_flow_mod_mod( const uint32_t transaction_id, const uint64_t cookie, 
                     const uint64_t cookie_mask, const uint8_t table_id,
                     const uint16_t idle_timeout, const uint16_t hard_timeout,
                     const uint16_t priority, const uint32_t buffer_id,
                     const uint16_t flags, const oxm_matches *oxm,
                     const openflow_instructions *instructions,
                     const bool strict, struct protocol *protocol ) {

  match *match = create_match( );
  if ( oxm != NULL && oxm->n_matches > 0 ) {
    for ( list_element *e = oxm->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  instruction_set *ins_set = create_instruction_set();
  if ( instructions != NULL ) {
    OFDPE ret = assign_instructions( ins_set, instructions->list );
    if ( ret != OFDPE_SUCCESS ) {
      send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPBIC_UNSUP_INST );
      delete_instruction_set( ins_set );
      delete_match( match );
      return;
    }
  }

  OFDPE ret = update_or_add_flow_entry( table_id, match, cookie, cookie_mask, priority, idle_timeout, hard_timeout,
                                        flags, strict, ins_set );
  delete_instruction_set( ins_set );
  delete_match( match );
  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
    return;
  }

  if ( buffer_id != OFP_NO_BUFFER ) {
    action_list *actions = create_action_list();
    action *action = create_action_output( OFPP_TABLE, UINT16_MAX );
    append_action( actions, action );
    ret = execute_packet_out( buffer_id, 0, actions, NULL );
    delete_action_list( actions );
    if ( ret != OFDPE_SUCCESS ) {
      uint16_t type = OFPET_FLOW_MOD_FAILED;
      uint16_t code = OFPFMFC_UNKNOWN;
      get_ofp_error( ret, &type, &code );
      send_error_message( transaction_id, type, code );
      return;
    }
    wakeup_datapath( protocol );
  }
}
示例#2
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 ) );
      }
    }
  }
示例#3
0
static void
handle_flow_mod_delete( const uint32_t transaction_id, const uint64_t cookie,
                        const uint64_t cookie_mask, const uint8_t table_id,
                        const uint16_t idle_timeout, const uint16_t hard_timeout,
                        const uint16_t priority, const uint32_t buffer_id,
                        const uint32_t out_port, const uint32_t out_group,
                        const uint16_t flags, const oxm_matches *oxm_match,
                        const openflow_instructions *instructions,
                        const bool strict ) {

  UNUSED( idle_timeout );
  UNUSED( hard_timeout );
  UNUSED( priority );
  UNUSED( buffer_id );
  UNUSED( flags );
  UNUSED( instructions );
  
  match *match = create_match();
  if ( oxm_match != NULL && oxm_match->n_matches > 0 ) {
    for ( list_element *e = oxm_match->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  OFDPE ret = OFDPE_FAILED;
  if ( strict ) {
    ret = delete_flow_entry_strict( table_id, match, cookie, cookie_mask, priority, out_port, out_group );
  }
  else {
    ret = delete_flow_entries( table_id, match, cookie, cookie_mask, out_port, out_group );
  }

  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
  }

  delete_match( match );
}
示例#4
0
static void
handle_flow_mod_add( const uint32_t transaction_id, const uint64_t cookie, 
                     const uint64_t cookie_mask, const uint8_t table_id,
                     const uint16_t idle_timeout, const uint16_t hard_timeout,
                     const uint16_t priority, const uint32_t buffer_id,
                     const uint16_t flags, const oxm_matches *oxm,
                     const openflow_instructions *instructions,
                     struct protocol *protocol ) {
  UNUSED( cookie_mask );
  /*
   * currently if flags set OFPFF_SEND_FLOW_REM and OFPFF_RESET_COUNTS are the only allowed value.
   */
  if ( ( flags & ~( OFPFF_SEND_FLOW_REM | OFPFF_RESET_COUNTS ) ) != 0 ) {
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_FLAGS );
    return;
  }
  /*
   * The use of OFPTT_ALL is only valid for delete requests.
   */
  if ( table_id == OFPTT_ALL ) {
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_TABLE_ID );
    return;
  }

  /*
   * If no buffered packet is associated with a flow mod it must be set
   * to OFP_NO_BUFFER otherwise it must be equal to the buffer_id sent to
   * controller by a packet-in message.
   */

  match *match = create_match();
  if ( oxm != NULL && oxm->n_matches > 0 ) {
    
#ifdef DEBUG    
    char oxm_str[ 2048 ];
    match_to_string( oxm, oxm_str, sizeof( oxm_str ) );
    printf( "%s\n", oxm_str );
#endif
    
    for ( list_element *e = oxm->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  instruction_set *instruction_set = create_instruction_set();
  if ( instructions != NULL ) {
    OFDPE ret = assign_instructions( instruction_set, instructions->list );
    if ( ret != OFDPE_SUCCESS ) {
      send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPBIC_UNSUP_INST );
      delete_instruction_set( instruction_set );
      delete_match( match );
      return;
    }
  }

  /*
   * When a flow entry is inserted in a table, its flags field is set with the
   * values from the message.
   * When a flow entry is inserted in a table, its idle_timeout and
   * hard_timeout fields are set with the values from the message.
   * When a flow entry is inserted in a table through an OFPFC_ADD message,
   * its cookie field is set to the provided value
   */
  flow_entry *new_entry = alloc_flow_entry( match, instruction_set, priority,
                                            idle_timeout, hard_timeout, flags, cookie );
  if ( new_entry == NULL ) {
    /*
     * TODO we should send a more appropriate error once we worked out the
     * datapath errors.
     */
    delete_instruction_set( instruction_set );
    delete_match( match );
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_UNKNOWN );
    return;
  }

  OFDPE ret = add_flow_entry( table_id, new_entry, flags );
  if ( ret != OFDPE_SUCCESS ) {
    error( "Failed to add a flow entry ( ret = %d ).", ret );
    delete_instruction_set( instruction_set );
    delete_match( match );

    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
    return;
  }

  if ( buffer_id != OFP_NO_BUFFER ) {
    action_list *actions = create_action_list();
    action *action = create_action_output( OFPP_TABLE, UINT16_MAX );
    append_action( actions, action );
    ret = execute_packet_out( buffer_id, 0, actions, NULL );
    delete_action_list( actions );
    if ( ret != OFDPE_SUCCESS ) {
      uint16_t type = OFPET_FLOW_MOD_FAILED;
      uint16_t code = OFPFMFC_UNKNOWN;
      get_ofp_error( ret, &type, &code );
      send_error_message( transaction_id, type, code );
      return;
    }
    wakeup_datapath( protocol );
  }
}
示例#5
0
static char *
parse_dump_flows( char *cmd, const uint64_t own_datapath_id ) {
  if ( prefixcmp( cmd, "dump_flows" ) ) {
    return NULL;
  }
  char *opt = strchr ( cmd, ' ' );
  assert( opt );

  uint64_t datapath_val;
  uint32_t in_port_val;
  uint16_t eth_type_val;
  uint8_t ip_proto_val;
  uint64_t metadata_val[ 2 ];
  uint16_t udp_src_val;
  uint16_t udp_dst_val;
  uint8_t table_id_val;
  uint32_t out_port_val;
  uint32_t out_group_val;
  uint64_t cookie_val[ 2 ];


  struct option opts[] = {
    OPT_UINT64( "--datapath_id", "datapath_id:", OPT_NO_MASK, &datapath_val ),
    OPT_UINT32( "--in_port", "in_port:", OPT_NO_MASK, &in_port_val ),
    OPT_UINT16( "--eth_type", "eth_type:", OPT_NO_MASK, &eth_type_val ),
    OPT_UINT8( "--ip_proto", "ip_proto:", OPT_NO_MASK, &ip_proto_val ),
    OPT_UINT64( "--metadata", "metadata:", OPT_HAS_MASK, &metadata_val ),
    OPT_UINT16( "--udp_src", "udp_src:", OPT_NO_MASK, &udp_src_val ),
    OPT_UINT16( "--udp_dst", "udp_dst:", OPT_NO_MASK, &udp_dst_val ),
    OPT_UINT8( "--table_id", "table_id:", OPT_NO_MASK, &table_id_val ),
    OPT_UINT64( "--cookie", "cookie:", OPT_HAS_MASK, &cookie_val ),
    OPT_UINT32( "--out_port", "out_port:", OPT_NO_MASK, &out_port_val ),
    OPT_UINT32( "--out_group", "out_group:", OPT_NO_MASK, &out_group_val ),
    OPT_END()
  };

  
  char *saveptr;
  const char *sep = " ";

  for ( opt = strtok_r( opt, sep, &saveptr ); opt; opt = strtok_r( NULL, sep, &saveptr ) ) {
    parse_option( opt, opts );
    if ( *( uint64_t * ) opts[ 0 ].value != own_datapath_id ) {
      return NULL;
    }
  }
  match *match = create_match();
  parse_match( match, opts );

  flow_stats *stats = NULL;
  uint32_t nr_stats;
  OFDPE ret = get_flow_stats( ( uint8_t ) table_id_val, match, cookie_val[ 0 ], cookie_val[ 1 ], out_port_val, out_group_val, &stats, &nr_stats );
  if ( ret != OFDPE_SUCCESS ) {
    error( "Failed to retrieve flow stats from datapath ( ret = %d ).", ret );
  }
  delete_match( match );
  
  char *reply_buf = xmalloc( PATH_MAX + 1 );
  reply_buf[ 0 ] = '\0';
  size_t used = 0;
  int left;
  const char *term = ",";
  const char *orig = "{ \"dump_flows\": [";
  if ( stats != NULL && nr_stats ) {
    for ( uint32_t i = 0; i < nr_stats; i++ ) {
      if ( i != 0 ) {
        orig = "";
      }
      if ( i == nr_stats - 1 ) {
        term = "]}";
      }
      left = snprintf( reply_buf + used, PATH_MAX - used, "%s {" DUMP_FLOW_FIELDS "} %s",
                       orig,
                       stats->table_id,
                       stats->duration_sec,
                       stats->priority,
                       stats->idle_timeout,
                       stats->hard_timeout, 
                       stats->flags,
                       stats->cookie,
                       stats->packet_count,
                       stats->byte_count,
                       term );
      used = ( size_t ) left - used;
      stats++;
    }
  }

  return reply_buf;
}