void _switch_response_timeout( void *user_data ) { struct txinfo *txinfo = user_data; const uint64_t dpid = txinfo->dpid; const uint32_t txid = txinfo->txid; // xfree( txinfo ); // cannot free since _switch_response_handler may be called later. txinfo = NULL; debug( "txid %#x switch %#" PRIx64 " time out. called", txid, dpid ); all_sw_tx *tx = lookup_hash_entry( efi_tx_table, &txid ); if ( tx == NULL ) { // transaction already failed. Do nothing. return; } uint64_t *dpid_in_list = lookup_hash_entry( tx->waiting_dpid, &dpid ); if ( dpid_in_list != NULL ) { info( "txid %#x switch %#" PRIx64 " timed out.", txid, dpid ); delete_hash_entry( tx->waiting_dpid, &dpid ); xfree( dpid_in_list ); tx->tx_result = EFI_OPERATION_FAILED; } check_tx_result_and_respond( tx ); }
static void handle_switch_disconnected( uint64_t datapath_id, void *switch_db ) { known_switch *sw = delete_hash_entry( switch_db, &datapath_id ); if ( sw != NULL ) { delete_switch( sw ); } }
static void handle_features_reply( uint64_t datapath_id, uint32_t transaction_id, uint32_t n_buffers, uint8_t n_tables, uint32_t capabilities, uint32_t actions, const list_element *phy_ports, void *user_data) { UNUSED( transaction_id ); UNUSED( n_buffers ); UNUSED( n_tables ); UNUSED( capabilities ); UNUSED( actions ); show_desc *show_desc = user_data; desc_entry *desc = lookup_hash_entry( show_desc->db, &datapath_id ); if ( desc == NULL ) { return; } display_desc( &desc->desc_stats ); display_datapath_id( datapath_id ); list_element ports_list; memcpy( &ports_list, phy_ports, sizeof( list_element ) ); for ( list_element *port = &ports_list; port != NULL; port = port->next ) { display_port( port->data ); } delete_hash_entry( show_desc->db, &datapath_id ); show_desc->count--; xfree( desc ); if ( show_desc->count == 0 ) { stop_trema(); } }
static void age_forwarding_db( void *mac, void *entry, void *forwarding_db ) { if ( aged_out( entry ) ) { delete_hash_entry( forwarding_db, mac ); xfree( entry ); } }
void delete_match_entry( struct ofp_match *ofp_match ) { match_entry *delete_entry; list_element *list; pthread_mutex_lock( match_table_head.mutex ); assert( ofp_match != NULL ); if ( !ofp_match->wildcards ) { delete_entry = delete_hash_entry( match_table_head.exact_table, ofp_match ); if ( delete_entry == NULL ) { pthread_mutex_unlock( match_table_head.mutex ); return; } } else { for ( list = match_table_head.wildcard_table; list != NULL; list = list->next ) { delete_entry = list->data; if ( ( ( ( delete_entry->ofp_match.wildcards ^ ofp_match->wildcards ) & OFPFW_ALL ) == 0 ) && compare_match( &delete_entry->ofp_match, ofp_match ) ) { break; } } if ( list == NULL ) { pthread_mutex_unlock( match_table_head.mutex ); return; } delete_element( &match_table_head.wildcard_table, delete_entry ); } free_match_entry( delete_entry ); pthread_mutex_unlock( match_table_head.mutex ); }
static bool delete_http_transaction( http_transaction *transaction ) { debug( "Deleting a HTTP transaction from database ( transaction = %p, handle = %p ).", transaction, transaction->handle ); assert( transaction != NULL ); assert( transaction->handle != NULL ); assert( transactions != NULL ); void *deleted = delete_hash_entry( transactions, transaction->handle ); if ( deleted == NULL ) { error( "Failed to delete a HTTP transaction ( transaction = %p, handle = %p ).", transaction, transaction->handle ); return false; } assert( deleted == transaction ); assert( curl_handle != NULL ); CURLMcode ret = curl_multi_remove_handle( curl_handle, transaction->handle ); if ( ret != CURLM_OK && ret != CURLM_CALL_MULTI_PERFORM ) { error( "Failed to remove an easy handle from a multi handle ( curl_handle = %p, handle = %p, error = %s ).", curl_handle, transaction->handle, curl_multi_strerror( ret ) ); } if ( transaction->slist != NULL ) { curl_slist_free_all( transaction->slist ); transaction->slist = NULL; } curl_easy_cleanup( transaction->handle ); transaction->handle = NULL; debug( "A HTTP transaction is deleted from database ( transaction = %p, handle = %p ).", transaction, transaction->handle ); return true; }
static void age_forwarding_db( void *key, void *forwarding_entry, void *forwarding_db ) { if ( aged_out( forwarding_entry ) ) { delete_hash_entry( forwarding_db, key ); xfree( forwarding_entry ); } }
void _switch_response_handler( event_forward_operation_result result, void *user_data ) { struct txinfo *txinfo = user_data; const uint64_t dpid = txinfo->dpid; const uint32_t txid = txinfo->txid; delete_timer_event( _switch_response_timeout, txinfo ); xfree( txinfo ); txinfo = NULL; debug( "txid %#x switch %#" PRIx64 " response.", txid, dpid ); all_sw_tx *tx = lookup_hash_entry( efi_tx_table, &txid ); if ( tx == NULL ) { // transaction already failed. Do nothing. return; } uint64_t *dpid_in_list = lookup_hash_entry( tx->waiting_dpid, &dpid ); if ( dpid_in_list == NULL ) { // probably timed out. Do nothing. return; } delete_hash_entry( tx->waiting_dpid, &dpid ); xfree( dpid_in_list ); dpid_in_list = NULL; if ( result.result == EFI_OPERATION_FAILED ) { warn( "txid %#x Setting event forwarding entry to switch %#" PRIx64 " failed.", txid, dpid ); tx->tx_result = EFI_OPERATION_FAILED; } bool tx_ended = check_tx_result_and_respond( tx ); if ( tx_ended ) return; struct event_forward_operation_to_all_request_param *all_param = tx->request_param; if ( hash_table_is_empty( tx->waiting_dpid ) ) { // was last element in tx. callback result. if ( all_param->callback != NULL ) { all_param->callback( tx->tx_result, all_param->user_data ); } info( "txid %#x complete.", tx->txid ); // remove and cleanup tx delete_hash_entry( efi_tx_table, &tx->txid ); xfree_all_sw_tx( tx ); return; } }
static void test_nonexistent_entry_returns_NULL() { table = create_hash( compare_string, hash_string ); assert_true( delete_hash_entry( table, "NO SUCH KEY" ) == NULL ); delete_hash( table ); }
static void test_foreach() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); insert_hash_entry( table, bravo, bravo ); insert_hash_entry( table, charlie, charlie ); delete_hash_entry( table, bravo ); delete_hash_entry( table, charlie ); foreach_hash( table, append_back_foreach, NULL ); assert_string_equal( abc[ 0 ], "alpha" ); assert_true( abc[ 1 ] == NULL ); assert_true( abc[ 2 ] == NULL ); delete_hash( table ); }
static void age_fdb_entry( void *key, void *value, void *user_data ) { hash_table *fdb = user_data; fdb_entry *entry = value; if ( entry->updated_at + FDB_ENTRY_TIMEOUT < time( NULL ) ) { debug( "Age out" ); void *deleted = delete_hash_entry( fdb, key ); xfree( deleted ); } }
static transaction_entry * delete_transaction_entry_by_xid( uint32_t transaction_id ) { debug( "Deleting a transaction entry by transaction id ( transaction_db = %p, transaction_id = %#x ).", transaction_db, transaction_id ); assert( transaction_db != NULL ); assert( transaction_db->xid != NULL ); assert( transaction_db->barrier_xid != NULL ); transaction_entry *deleted = delete_hash_entry( transaction_db->xid, &transaction_id ); if ( deleted != NULL ) { debug( "A transaction entry is deleted by transaction_id ( transaction_db = %p, transaction_id = %#x ).", transaction_db, transaction_id ); debug( "Deleting a transaction entry by barrier transaction id ( transaction_db = %p, transaction_id = %#x ).", transaction_db, transaction_id ); delete_hash_entry( transaction_db->barrier_xid, &deleted->barrier_xid ); } else { debug( "Failed to delete a transaction entry by transaction_id ( transaction_db = %p, transaction_id = %#x ).", transaction_db, transaction_id ); } return deleted; }
void _cleanup_tx_table() { hash_iterator it; init_hash_iterator( efi_tx_table, &it ); hash_entry *e = NULL; while ( ( e = iterate_hash_next( &it ) ) != NULL ) { all_sw_tx *tx = e->value; warn( "txid:%#x was left behind.", tx->txid ); delete_hash_entry( efi_tx_table, &tx->txid ); xfree_all_sw_tx( tx ); } }
void delete_dpid_entry( uint64_t *dpid ) { assert( dpid_table != NULL ); assert( dpid != NULL ); uint64_t *deleted_entry = delete_hash_entry( dpid_table, dpid ); if ( deleted_entry == NULL ) { warn( "datapath %#" PRIx64 " is not found.", *dpid ); return; } xfree( deleted_entry ); }
static void test_multiple_inserts_and_deletes_then_iterate() { table = create_hash( compare_string, hash_string ); char one[] = "one"; insert_hash_entry( table, one, ( void * ) 1 ); delete_hash_entry( table, one ); insert_hash_entry( table, one, ( void * ) 1 ); delete_hash_entry( table, one ); insert_hash_entry( table, one, ( void * ) 1 ); int sum = 0; hash_iterator iter; hash_entry *e; init_hash_iterator( table, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { sum += ( int ) ( uintptr_t ) e->value; delete_hash_entry( table, e->key ); } assert_true( sum == 1 ); delete_hash( table ); }
/** * Delete the global hash_table which stored the stats of parameters. * @param None * @return None */ static void delete_stats_table() { hash_iterator iter; hash_entry *e; assert( stats != NULL ); init_hash_iterator( stats, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { void *value = delete_hash_entry( stats, e->key ); xfree( value ); } delete_hash( stats ); stats = NULL; }
static void test_delete_entry() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); insert_hash_entry( table, bravo, bravo ); insert_hash_entry( table, charlie, charlie ); delete_hash_entry( table, bravo ); assert_string_equal( lookup_hash_entry( table, alpha ), "alpha" ); assert_true( lookup_hash_entry( table, bravo ) == NULL ); assert_string_equal( lookup_hash_entry( table, charlie ), "charlie" ); delete_hash( table ); }
static void age_host_db_entry( void *key, void *value, void *user_data ) { UNUSED( user_data ); host_entry *entry = value; if ( entry->updated_at + HOST_DB_ENTRY_TIMEOUT < time( NULL ) ) { struct in_addr addr; addr.s_addr = htonl( entry->ip ); debug( "Host DB: age out (ip = %s).", inet_ntoa( addr ) ); delete_host_route( entry->ip ); void *deleted = delete_hash_entry( host_db, key ); xfree( deleted ); } }
void delete_xid_entry( xid_entry_t *delete_entry ) { debug( "Deleting xid entry ( xid = %#lx, original_xid = %#lx, service_name = %s, index = %d ).", delete_entry->xid, delete_entry->original_xid, delete_entry->service_name, delete_entry->index ); xid_entry_t *deleted = delete_hash_entry( xid_table.hash, &delete_entry->xid ); if ( deleted == NULL ) { error( "Failed to delete xid entry ( xid = %#lx ).", delete_entry->xid ); free_xid_entry( ( xid_entry_t * ) delete_entry ); return; } xid_table.entries[ deleted->index ] = NULL; free_xid_entry( deleted ); }
static bool check_tx_result_and_respond( all_sw_tx *tx ) { if ( tx->tx_result == EFI_OPERATION_FAILED ) { struct event_forward_operation_to_all_request_param *all_param = tx->request_param; if ( all_param->callback != NULL ) { all_param->callback( tx->tx_result, all_param->user_data ); } info( "txid %#x completed with failure.", tx->txid ); // remove and cleanup tx delete_hash_entry( efi_tx_table, &tx->txid ); xfree_all_sw_tx( tx ); return true; } return false; }
static void test_iterator() { table = create_hash( compare_string, hash_string ); char one[] = "one"; insert_hash_entry( table, one, ( void * ) 1 ); char two[] = "two"; insert_hash_entry( table, two, ( void * ) 2 ); char three[] = "three"; insert_hash_entry( table, three, ( void * ) 3 ); char four[] = "four"; insert_hash_entry( table, four, ( void * ) 4 ); char five[] = "five"; insert_hash_entry( table, five, ( void * ) 5 ); char six[] = "six"; insert_hash_entry( table, six, ( void * ) 6 ); char seven[] = "seven"; insert_hash_entry( table, seven, ( void * ) 7 ); char eight[] = "eight"; insert_hash_entry( table, eight, ( void * ) 8 ); char nine[] = "nine"; insert_hash_entry( table, nine, ( void * ) 9 ); char ten[] = "ten"; insert_hash_entry( table, ten, ( void * ) 10 ); int sum = 0; hash_iterator iter; hash_entry *e; init_hash_iterator( table, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { sum += ( int ) ( uintptr_t ) e->value; delete_hash_entry( table, e->key ); } assert_true( sum == 55 ); delete_hash( table ); }
static void * delete_exact_match_strict_entry( hash_table *exact_table, struct ofp_match *match ) { assert( exact_table != NULL ); assert( match != NULL ); match_entry *entry = lookup_hash_entry( exact_table, match ); if ( entry == NULL ) { char match_string[ MATCH_STRING_LENGTH ]; match_to_string( match, match_string, sizeof( match_string ) ); warn( "exact match entry not found ( match = [%s] )", match_string ); return NULL; } void *data = entry->data; delete_hash_entry( exact_table, match ); free_match_entry( entry ); return data; }
void print_with_graph_easy_format( void *param, size_t entries, const topology_link_status *s ) { size_t i; UNUSED( param ); debug( "topology: entries %d", entries ); hash_table *link_hash = create_hash( compare_link, hash_link ); // show_topology graph-easy | graph-easy // Graph-Easy: // http://search.cpan.org/~shlomif/Graph-Easy/bin/graph-easy printf("#! /usr/bin/env graph-easy\n" ); for ( i = 0; i < entries; i++ ) { if ( s[ i ].status != TD_LINK_UP ) { continue; } topology_link_status r; r.from_dpid = s[ i ].to_dpid; r.from_portno = s[ i ].to_portno; r.to_dpid = s[ i ].from_dpid; r.to_portno = s[ i ].from_portno; topology_link_status *e = lookup_hash_entry( link_hash, &r ); if ( e != NULL ) { delete_hash_entry( link_hash, e ); print_link_status( e, true ); } else { insert_hash_entry( link_hash, ( void * ) ( intptr_t ) &s[ i ], ( void *) ( intptr_t ) &s[ i ] ); } } hash_iterator iter; init_hash_iterator( link_hash, &iter ); hash_entry *e; while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { topology_link_status *le = e->value; print_link_status( le, false ); } delete_hash( link_hash ); stop_trema(); }
static void handle_port_desc_reply( uint64_t datapath_id, uint32_t transaction_id, uint16_t type, uint16_t flags, const buffer *data, void *user_data ) { UNUSED( transaction_id ); UNUSED( type ); UNUSED( flags ); show_desc *show_desc = user_data; desc_entry *desc = lookup_hash_entry( show_desc->db, &datapath_id ); if ( desc == NULL ) { return; } append_to_tail( &desc->port_desc, duplicate_buffer( data ) ); if ( more_requests( flags ) ) { return; } display_desc( &desc->desc_stats ); display_datapath_id( datapath_id ); for ( list_element *e = desc->port_desc; e != NULL; e = e->next ) { buffer *data = e->data; struct ofp_port *port = ( struct ofp_port * ) data->data; size_t length = data->length; while ( length >= sizeof( struct ofp_port ) ) { display_port( port ); length -= ( uint16_t ) sizeof( struct ofp_port ); port++; } free_buffer( e->data ); } delete_list( desc->port_desc ); delete_hash_entry( show_desc->db, &datapath_id ); show_desc->count--; xfree( desc ); if ( show_desc->count == 0 ) { stop_trema(); } }
static bool delete_transaction( uint64_t datapath_id, uint32_t vni ) { debug( "Deleting a transaction record ( datapath_id = %#" PRIx64 ", vni = %#x ).", datapath_id, vni ); if ( !valid_vni( vni ) ) { return false; } transaction_entry key = { datapath_id, vni, 0, 0, 0, 0, NULL, NULL }; transaction_entry *entry = delete_hash_entry( transactions, &key ); if ( entry == NULL ) { error( "Failed to find a transaction entry ( datapath_id %" PRIx64 ", vni = %#x ).", key.datapath_id, key.vni ); return false; } xfree( entry ); debug( "A transaction record is deleted ( datapath_id = %#" PRIx64 ", vni = %#x ).", datapath_id, vni ); return true; }
void finalize_switch_port() { assert( switch_ports != NULL ); hash_iterator iter; hash_entry *e; init_hash_iterator( switch_ports, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { switch_port *port = delete_hash_entry( switch_ports, e->key ); if ( port == NULL ) { continue; } if ( port->device != NULL ) { delete_ether_device( port->device ); } xfree( port ); } delete_hash( switch_ports ); switch_ports = NULL; }
void delete_fdb_entries( hash_table *fdb, uint64_t dpid, uint16_t port ) { if ( fdb == NULL ) { return; } debug( "Deleting fdb entries ( dpid = %#" PRIx64 ", port = %u ).", dpid, port ); fdb_entry *entry = NULL; hash_iterator iter; hash_entry *e; init_hash_iterator( fdb, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { if ( e->value == NULL ) { continue; } entry = e->value; if ( entry->dpid == dpid && entry->port == port ) { delete_hash_entry( fdb, entry->mac ); xfree( entry ); } } }
void _dispatch_to_all_switch( uint64_t *dpids, size_t n_dpids, void *user_data ) { struct event_forward_operation_to_all_request_param *param = user_data; all_sw_tx *tx = _insert_tx( n_dpids, param ); info( "txid %#x Start dispatching to switches", tx->txid ); debug( "dispatching to %zd switches", n_dpids ); // copy dpid hash to transaction. for ( size_t i = 0 ; i < n_dpids ; ++i ) { uint64_t *dpid = xmalloc( sizeof( uint64_t ) ); *dpid = dpids[i]; uint64_t *dupe_dpid = insert_hash_entry( tx->waiting_dpid, dpid, dpid ); if ( dupe_dpid == NULL ) { struct txinfo *txinfo = xcalloc( 1, sizeof( struct txinfo ) ); txinfo->dpid = *dpid; txinfo->txid = tx->txid; bool send_ok; if ( param->add ) { send_ok = add_switch_event_forward_entry( *dpid, param->type, param->service_name, _switch_response_handler, txinfo ); } else { send_ok = delete_switch_event_forward_entry( *dpid, param->type, param->service_name, _switch_response_handler, txinfo ); } if ( !send_ok ) { tx->tx_result = EFI_OPERATION_FAILED; warn( "txid %#x Failed to send request to switch %#" PRIx64 ".", tx->txid, *dpid ); xfree( delete_hash_entry( tx->waiting_dpid, dpid ) ); dpid = NULL; xfree( txinfo ); continue; } struct itimerspec interval; interval.it_interval.tv_sec = 0; interval.it_interval.tv_nsec = 0; interval.it_value.tv_sec = 5; // FIXME make this configurable? interval.it_value.tv_nsec = 0; bool set_ok = add_timer_event_callback( &interval, _switch_response_timeout, txinfo ); if ( !set_ok ) { tx->tx_result = EFI_OPERATION_FAILED; warn( "txid %#x Failed to set timeout timer for switch %#" PRIx64 ".", tx->txid, *dpid ); xfree( delete_hash_entry( tx->waiting_dpid, dpid ) ); dpid = NULL; // txinfo will be freed by _switch_response_handler continue; } } else { warn( "Duplicate dpid returned %#." PRIx64, *dupe_dpid ); xfree( dupe_dpid ); } } if ( n_dpids == 0 || tx->tx_result == EFI_OPERATION_FAILED ) { if ( n_dpids == 0 ) { info( "txid %#x completed. No switches found.", tx->txid ); } else if ( tx->tx_result == EFI_OPERATION_FAILED ) { info( "txid %#x completed with failure.", tx->txid ); } if ( param->callback != NULL ) { param->callback( tx->tx_result, param->user_data ); } // remove and cleanup tx delete_hash_entry( efi_tx_table, &tx->txid ); xfree_all_sw_tx( tx ); } }
void delete_datapath_entry( hash_table *db, uint64_t datapath_id ) { datapath_entry *entry = delete_hash_entry( db, &datapath_id ); free_datapath_entry( entry ); debug( "delete datapath: %#" PRIx64 " ( entry = %p )", datapath_id, entry ); }
switch_port * delete_switch_port( uint32_t port_no ) { assert( switch_ports != NULL ); return delete_hash_entry( switch_ports, &port_no ); }