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 bool add_transaction( uint64_t datapath_id, uint32_t vni, int operation, overlay_operation_completed_handler callback, void *user_data ) { debug( "Adding a transaction record ( datapath_id = %#" PRIx64 ", vni = %#x, operation = %#x, callback = %p, user_data = %p ).", datapath_id, vni, operation, callback, user_data ); if ( !valid_vni( vni ) ) { return false; } transaction_entry *entry = xmalloc( sizeof( transaction_entry ) ); memset( entry, 0, sizeof( transaction_entry ) ); entry->datapath_id = datapath_id; entry->vni = vni; entry->operation = operation; entry->port_wait_count = 0; entry->n_ongoing_http_requests = 0; entry->n_failed_http_requests = 0; entry->callback = callback; entry->user_data = user_data; entry = insert_hash_entry( transactions, entry, entry ); if ( entry != NULL ) { warn( "Duplicated transaction record found ( datapath_id = %#" PRIx64 ", vni = %#x, operation = %#x, callback = %p, user_data = %p ).", datapath_id, vni, operation, callback, user_data ); xfree( entry ); } debug( "A transaction record is added ( datapath_id = %#" PRIx64 ", vni = %#x, operation = %#x, callback = %p, user_data = %p ).", datapath_id, vni, operation, callback, user_data ); return true; }
static void handle_desc_stats_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; if ( data->length < SIZE_OF_OFP_DESC ) { error( "invalid data" ); stop_trema(); return; } desc_entry *entry = xmalloc( sizeof( desc_entry ) ); entry->datapath_id = datapath_id; #ifdef TREMA_EDGE create_list( &entry->port_desc ); #endif memcpy( &entry->desc_stats, data->data, SIZE_OF_OFP_DESC ); insert_hash_entry( show_desc->db, &entry->datapath_id, entry ); #ifdef TREMA_EDGE buffer *port_desc_request = create_port_desc_multipart_request( get_transaction_id(), 0 ); send_openflow_message( datapath_id, port_desc_request ); free_buffer( port_desc_request ); #else buffer *features_request = create_features_request( get_transaction_id() ); send_openflow_message( datapath_id, features_request ); free_buffer( features_request ); #endif }
uint32_t insert_xid_entry( uint32_t original_xid, char *service_name ) { xid_entry_t *new_entry; debug( "Inserting xid entry ( original_xid = %#lx, service_name = %s ).", original_xid, service_name ); if ( xid_table.next_index >= XID_MAX_ENTRIES ) { xid_table.next_index = 0; } if ( xid_table.entries[ xid_table.next_index ] != NULL ) { delete_xid_entry( xid_table.entries[ xid_table.next_index ] ); } new_entry = allocate_xid_entry( original_xid, service_name, xid_table.next_index ); xid_entry_t *old = insert_hash_entry( xid_table.hash, &new_entry->xid, new_entry ); if ( old != NULL ) { xid_table.entries[ old->index ] = NULL; free_xid_entry( old ); } xid_table.entries[ xid_table.next_index ] = new_entry; xid_table.next_index++; return new_entry->xid; }
/** * Adds a parameter to the Statistics database/table, stats of which are to be tracked. * @param key Identifier for the parameter of which stats are required * @return bool True if the entry was successfully added, else False in case entry already exists */ bool add_stat_entry( const char *key ) { assert( key != NULL ); pthread_mutex_lock( &stats_table_mutex ); stat_entry *entry = lookup_hash_entry( stats, key ); if ( entry != NULL ) { error( "Statistic entry for %s already exists.", key ); pthread_mutex_unlock( &stats_table_mutex ); return false; } entry = xmalloc( sizeof( stat_entry ) ); entry->value = 0; strncpy( entry->key, key, STAT_KEY_LENGTH ); entry->key[ STAT_KEY_LENGTH - 1 ] = '\0'; insert_hash_entry( stats, entry->key, entry ); pthread_mutex_unlock( &stats_table_mutex ); return true; }
static void test_insert_twice_overwrites_old_value() { char *prev; char key[] = "key"; table = create_hash( compare_string, hash_string ); char old_value[] = "old value"; char new_value[] = "new value"; insert_hash_entry( table, key, old_value ); prev = insert_hash_entry( table, key, new_value ); assert_string_equal( lookup_hash_entry( table, key ), "new value" ); assert_string_equal( prev, "old value" ); delete_hash( table ); }
static void test_map() { table = create_hash( compare_string, hash_string ); char key[] = "key"; insert_hash_entry( table, key, alpha ); insert_hash_entry( table, key, bravo ); insert_hash_entry( table, key, charlie ); map_hash( table, key, append_back, NULL ); assert_string_equal( abc0[ 0 ], "charlie" ); assert_string_equal( abc0[ 1 ], "bravo" ); assert_string_equal( abc0[ 2 ], "alpha" ); 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 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 test_insert_and_lookup() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); assert_string_equal( lookup_hash_entry( table, alpha ), "alpha" ); delete_hash( table ); }
static bool add_transaction_entry( transaction_entry *entry ) { debug( "Adding a transaction entry ( entry = %p, transaction_db = %p ).", entry, transaction_db ); assert( entry != NULL ); assert( transaction_db != NULL ); assert( transaction_db->xid != NULL ); assert( transaction_db->barrier_xid != NULL ); bool ret = get_monotonic_time( &entry->expires_at ); if ( !ret ) { return false; } ADD_TIMESPEC( &entry->expires_at, &TRANSACTION_TIMEOUT, &entry->expires_at ); dump_transaction_entry( debug, entry ); if ( lookup_transaction_entry_by_xid( entry->xid ) == NULL ) { void *duplicated = insert_hash_entry( transaction_db->xid, &entry->xid, entry ); assert( duplicated == NULL ); } else { error( "Duplicated transaction entry found ( entry = %p, xid = %#x ).", entry, entry->xid ); dump_transaction_entry( error, entry ); return false; } if ( lookup_transaction_entry_by_barrier_xid( entry->barrier_xid ) == NULL ) { void *duplicated = insert_hash_entry( transaction_db->barrier_xid, &entry->barrier_xid, entry ); assert( duplicated == NULL ); } else { error( "Duplicated transaction entry found ( entry = %p, barrier_xid = %#x ).", entry, entry->barrier_xid ); dump_transaction_entry( error, entry ); delete_transaction_entry_by_xid( entry->xid ); return false; } debug( "A transaction is added." ); dump_transaction_entry( debug, entry ); return true; }
void insert_datapath_entry( hash_table *db, uint64_t datapath_id, void *user_data, void delete_user_data( void *user_data ) ) { datapath_entry *entry = allocate_datapath_entry( datapath_id, user_data, delete_user_data ); debug( "insert datapath: %#" PRIx64 " ( entry = %p )", datapath_id, entry ); datapath_entry *old_datapath_entry = insert_hash_entry( db, &entry->id, entry ); if ( old_datapath_entry != NULL ) { warn( "duplicated datapath ( datapath_id = %#" PRIx64 ", entry = %p )", datapath_id, old_datapath_entry ); free_datapath_entry( old_datapath_entry ); } }
static void test_insert_and_lookup_by_atom_hash() { key mykey = { "alpha" }; table = create_hash( compare_atom, hash_atom ); insert_hash_entry( table, &mykey, alpha ); assert_string_equal( lookup_hash_entry( table, &mykey ), "alpha" ); delete_hash( table ); }
static void handle_switch_ready( uint64_t datapath_id, void *switch_db ) { known_switch *sw = lookup_hash_entry( switch_db, &datapath_id ); if ( sw == NULL ) { sw = new_switch( datapath_id ); insert_hash_entry( switch_db, &sw->datapath_id, sw ); } else { refresh( sw ); } }
static void learn( hash_table *forwarding_db, uint16_t port_no, uint8_t *mac ) { forwarding_entry *entry = lookup_hash_entry( forwarding_db, mac ); if ( entry == NULL ) { entry = xmalloc( sizeof( forwarding_entry ) ); memcpy( entry->mac, mac, sizeof( entry->mac ) ); insert_hash_entry( forwarding_db, entry->mac, entry ); } entry->port_no = port_no; entry->last_update = now(); }
void learn_fdb( hash_table *db, uint8_t *mac, uint16_t port_number ) { fdb *entry = lookup_hash_entry( db, mac ); if ( entry == NULL ) { entry = xmalloc( sizeof( fdb ) ); memcpy( entry->mac, mac, ETH_ADDRLEN ); entry->port_number = port_number; insert_hash_entry( db, entry->mac, entry ); } else { entry->port_number = port_number; } }
all_sw_tx* _insert_tx( size_t n_dpids, struct event_forward_operation_to_all_request_param *param ) { all_sw_tx *tx = xcalloc( 1, sizeof(all_sw_tx) ); tx->txid = get_txid(); tx->request_param = param; tx->tx_result = EFI_OPERATION_SUCCEEDED; tx->waiting_dpid = create_hash_with_size( compare_datapath_id, hash_datapath_id, ( unsigned ) n_dpids ); void *dupe_tx = insert_hash_entry( efi_tx_table, &tx->txid, tx ); assert( dupe_tx == NULL ); return tx; }
void add_counter( hash_table *db, uint8_t *mac, uint64_t packet_count, uint64_t byte_count ) { counter *entry = lookup_hash_entry( db, mac ); if ( entry == NULL ) { entry = xmalloc( sizeof( counter ) ); memcpy( entry->mac, mac, ETH_ADDRLEN ); entry->packet_count = 0; entry->byte_count = 0; insert_hash_entry( db, entry->mac, entry ); } entry->packet_count += packet_count; entry->byte_count += byte_count; }
static void learn( hash_table *forwarding_db, struct key new_key, uint16_t port_no ) { forwarding_entry *entry = lookup_hash_entry( forwarding_db, &new_key ); if ( entry == NULL ) { entry = xmalloc( sizeof( forwarding_entry ) ); memcpy( entry->key.mac, new_key.mac, OFP_ETH_ALEN ); entry->key.datapath_id = new_key.datapath_id; insert_hash_entry( forwarding_db, &entry->key, entry ); } entry->port_no = port_no; entry->last_update = now(); }
bool update_fdb( hash_table *fdb, const uint8_t mac[ OFP_ETH_ALEN ], uint64_t dpid, uint16_t port ) { assert( fdb != NULL ); assert( mac != NULL ); assert( port != 0 ); fdb_entry *entry = lookup_hash_entry( fdb, mac ); debug( "Updating fdb ( mac = %02x:%02x:%02x:%02x:%02x:%02x, dpid = %#" PRIx64 ", port = %u ).", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], dpid, port ); if ( entry != NULL ) { if ( ( entry->dpid == dpid ) && ( entry->port == port ) ) { entry->updated_at = time( NULL ); return true; } if ( entry->created_at + HOST_MOVE_GUARD_SEC < time( NULL ) ) { // Poisoning when the terminal moves poison( entry->dpid, mac ); entry->dpid = dpid; entry->port = port; entry->created_at = time( NULL ); entry->updated_at = entry->created_at; return true; } warn( "Failed to update fdb because host move detected in %d sec " "( mac = %02x:%02x:%02x:%02x:%02x:%02x, " "dpid = %#" PRIx64 " -> %#" PRIx64 ", port = %u -> %u ).", HOST_MOVE_GUARD_SEC, mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], entry->dpid, dpid, entry->port, port ); return false; } entry = xmalloc( sizeof( fdb_entry ) ); entry->dpid = dpid; memcpy( entry->mac, mac, OFP_ETH_ALEN ); entry->port = port; entry->created_at = time( NULL ); entry->updated_at = entry->created_at; insert_hash_entry( fdb, entry->mac, entry ); return true; }
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 ); }
void insert_dpid_entry( uint64_t *dpid ) { assert( dpid_table != NULL ); assert( dpid != NULL ); if ( lookup_hash_entry( dpid_table, dpid ) != NULL ) { warn( "datapath %#" PRIx64 " is already registered.", *dpid ); return; } uint64_t *new_entry = xmalloc( sizeof ( uint64_t ) ); *new_entry = *dpid; insert_hash_entry( dpid_table, new_entry, new_entry ); }
void insert_match_entry( struct ofp_match *ofp_match, uint16_t priority, const char *service_name, const char *entry_name ) { match_entry *new_entry, *entry; list_element *list; pthread_mutex_lock( match_table_head.mutex ); new_entry = allocate_match_entry( ofp_match, priority, service_name, entry_name ); if ( !ofp_match->wildcards ) { entry = lookup_hash_entry( match_table_head.exact_table, ofp_match ); if ( entry != NULL ) { warn( "insert entry exits" ); free_match_entry( new_entry ); pthread_mutex_unlock( match_table_head.mutex ); return; } insert_hash_entry( match_table_head.exact_table, &new_entry->ofp_match, new_entry ); pthread_mutex_unlock( match_table_head.mutex ); return; } // wildcard flags are set for ( list = match_table_head.wildcard_table; list != NULL; list = list->next ) { entry = list->data; if ( entry->priority <= new_entry->priority ) { break; } } if ( list == NULL ) { // wildcard_table is null or tail append_to_tail( &match_table_head.wildcard_table, new_entry ); pthread_mutex_unlock( match_table_head.mutex ); return; } if ( list == match_table_head.wildcard_table ) { // head insert_in_front( &match_table_head.wildcard_table, new_entry ); pthread_mutex_unlock( match_table_head.mutex ); return; } // insert brefore insert_before( &match_table_head.wildcard_table, list->data, new_entry ); pthread_mutex_unlock( match_table_head.mutex ); }
static bool insert_exact_match_entry( hash_table *exact_table, struct ofp_match *match, void *data ) { 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 already exists ( match = [%s] )", match_string ); return false; } match_entry *new_entry = allocate_match_entry( match, 0 /* dummy priority */, data ); match_entry *conflict_entry = insert_hash_entry( exact_table, &new_entry->match, new_entry ); assert( conflict_entry == NULL ); return true; }
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(); }
switch_port * add_switch_port( const char *interface, uint32_t port_no, const size_t max_send_queue, const size_t max_recv_queue ) { assert( interface != NULL ); assert( switch_ports != NULL ); switch_port *port = ( switch_port * ) xmalloc( sizeof( switch_port ) ); memset( port, 0, sizeof( switch_port ) ); port->port_no = port_no; port->device = create_ether_device( interface, max_send_queue, max_recv_queue ); if ( port->device == NULL ) { xfree( port ); return NULL; } insert_hash_entry( switch_ports, &port->port_no, port ); return port; }
static void grow_hash_table(struct hash_table *table) { unsigned int i; unsigned int old_size = table->size, new_size; struct hash_table_entry *old_array = table->array, *new_array; new_size = alloc_nr(old_size); new_array = xzmalloc(sizeof(struct hash_table_entry) * new_size); table->size = new_size; table->array = new_array; table->nr = 0; for (i = 0; i < old_size; i++) { unsigned int hash = old_array[i].hash; void *ptr = old_array[i].ptr; if (ptr) insert_hash_entry(hash, ptr, table); } if (old_array) xfree(old_array); }
static void add_host( const uint8_t *mac, const uint32_t ip, const uint64_t dpid, const uint16_t port ) { host_entry *entry; struct in_addr addr; addr.s_addr = htonl( ip ); entry = lookup_host( ip ); if ( entry != NULL ) { debug( "Updating a host entry (mac = %02x:%02x:%02x:%02x:%02x:%02x, " "ip = %s, dpid = %#" PRIx64 ", port = %u).", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], inet_ntoa( addr ), dpid, port ); memcpy( entry->mac, mac, ETH_ADDRLEN ); entry->dpid = dpid; entry->port = port; entry->updated_at = time( NULL ); return; } debug( "Adding a host entry (mac = %02x:%02x:%02x:%02x:%02x:%02x, " "ip = %s, dpid = %#" PRIx64 ", port = %u).", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], inet_ntoa( addr ), dpid, port ); entry = xmalloc( sizeof( host_entry ) ); memcpy( entry->mac, mac, ETH_ADDRLEN ); entry->ip = ip; entry->dpid = dpid; entry->port = port; entry->updated_at = time( NULL ); insert_hash_entry( host_db, &entry->ip, entry ); add_host_route( entry->ip ); }
static bool add_http_transaction( http_transaction *transaction, CURL *handle ) { debug( "Adding a HTTP transaction to database ( transaction = %p, handle = %p ).", transaction, handle ); assert( transaction != NULL ); assert( handle != NULL ); transaction->handle = handle; assert( curl_handle != NULL ); CURLMcode ret = curl_multi_add_handle( curl_handle, transaction->handle ); if ( ret != CURLM_OK && ret != CURLM_CALL_MULTI_PERFORM ) { error( "Failed to add an easy handle to a multi handle ( curl_handle = %p, handle = %p, error = %s ).", curl_handle, transaction->handle, curl_multi_strerror( ret ) ); return false; } ret = curl_multi_perform( curl_handle, &curl_running ); if ( ret != CURLM_OK && ret != CURLM_CALL_MULTI_PERFORM ) { error( "Failed to run a multi handle ( curl_handle = %p, error = %s ).", curl_handle, curl_multi_strerror( ret ) ); 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 ) ); } return false; } assert( transactions != NULL ); void *duplicated = insert_hash_entry( transactions, transaction->handle, transaction ); if ( duplicated != NULL ) { // FIXME: handle duplication properly warn( "Duplicated HTTP transaction found ( %p ).", duplicated ); free_http_transaction( duplicated ); } debug( "A HTTP transaction is added into database ( transaction = %p, handle = %p ).", transaction, handle ); return true; }
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 ); } }