static list_element * lookup_flow_entries_with_table_id( const uint8_t table_id, const match *match, const uint16_t priority, const bool strict, const bool update_counters ) { assert( valid_table_id( table_id ) ); if ( get_logging_level() >= LOG_DEBUG ) { debug( "Looking up flow entries ( table_id = %#x, match = %p, priority = %u, strict = %s, update_counters = %s ).", table_id, match, priority, strict ? "true" : "false", update_counters ? "true" : "false" ); if ( match != NULL ) { dump_match( match, debug ); } } flow_table *table = get_flow_table( table_id ); if ( table == NULL ) { return NULL; } if ( update_counters ) { increment_lookup_count( table_id ); } list_element *head = NULL; create_list( &head ); for ( list_element *e = table->entries; e != NULL; e = e->next ) { flow_entry *entry = e->data; assert( entry != NULL ); if ( strict ) { if ( entry->priority < priority ) { break; } if ( priority == entry->priority && compare_match_strict( match, entry->match ) ) { if ( update_counters ) { increment_matched_count( table_id ); } append_to_tail( &head, entry ); break; } } else { if ( compare_match( match, entry->match ) ) { if ( update_counters ) { increment_matched_count( table_id ); } append_to_tail( &head, entry ); } } } return head; }
static list_element * get_switch_ports_to_output( const uint32_t port_no, const uint32_t in_port ) { assert( port_no > 0 ); assert( in_port <= OFPP_MAX ); switch_port_list ports; create_list( &ports.list ); ports.in_port = in_port; switch ( port_no ) { case OFPP_IN_PORT: { switch_port *port = lookup_switch_port( in_port ); if ( port != NULL ) { append_to_tail( &ports.list, port ); } } break; case OFPP_FLOOD: case OFPP_ALL: { foreach_switch_port( append_switch_port_to_list, &ports ); } break; case OFPP_TABLE: case OFPP_NORMAL: case OFPP_CONTROLLER: case OFPP_LOCAL: case OFPP_ANY: { warn( "Invalid port number ( port_no = %u, in_port = %u ).", port_no, in_port ); } break; default: { switch_port *port = lookup_switch_port( port_no ); if ( port != NULL ) { append_to_tail( &ports.list, port ); } } break; } return ports.list; }
OFDPE add_meter_entry( const uint16_t flags, const uint32_t meter_id, const list_element *bands ) { assert( table != NULL ); if ( meter_id == 0 || ( meter_id > OFPM_MAX && meter_id != OFPM_CONTROLLER )) { return ERROR_OFDPE_METER_MOD_FAILED_INVALID_METER; } meter_entry *entry = alloc_meter_entry( flags, meter_id, bands ); if ( entry == NULL ) { return ERROR_INVALID_PARAMETER; } OFDPE ret = OFDPE_SUCCESS; if ( !lock_pipeline() ) { free_meter_entry( entry ); return ERROR_LOCK; } if ( NULL != lookup_meter_entry( entry->meter_id ) ) { ret = ERROR_OFDPE_METER_MOD_FAILED_METER_EXISTS; free_meter_entry( entry ); } else { append_to_tail( &table->entries, entry ); } if ( !unlock_pipeline() ) { free_meter_entry( entry ); return ERROR_UNLOCK; } return ret; }
static void handle_packet_in( uint64_t datapath_id, uint32_t transaction_id, uint32_t buffer_id, uint16_t total_len, uint16_t in_port, uint8_t reason, const buffer *data, void *user_data ) { services *services = user_data; list_element **list_head = &services->arp_or_unicast; packet_info *packet_info = data->user_data; if ( !packet_type_arp( data ) && ( packet_info->eth_macda[ 0 ] & 0x1 ) == 0x1 ) { list_head = &services->broadcast; } if ( *list_head == NULL ) { return; } buffer *buf = create_packet_in( transaction_id, buffer_id, total_len, in_port, reason, data ); openflow_service_header_t *message; message = append_front_buffer( buf, sizeof( openflow_service_header_t ) ); message->datapath_id = htonll( datapath_id ); message->service_name_length = htons( 0 ); char *service_name = ( *list_head )->data; if ( send_message( service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { debug( "Sending a message to %s.", service_name ); } free_buffer( buf ); if ( ( *list_head )->next != NULL ) { //round robin delete_element( list_head, service_name ); append_to_tail( list_head, service_name ); } }
void add_outbound_port( list_element **switches, uint64_t dpid, uint16_t port_no ) { assert( port_no != 0 ); info( "Adding a port: dpid = %#" PRIx64 ", port = %u", dpid, port_no ); // lookup switch switch_info *sw = lookup_switch( *switches, dpid ); if ( sw == NULL ) { sw = allocate_switch( dpid ); append_to_tail( switches, sw ); } port_info *new_port = allocate_port( dpid, port_no ); append_to_tail( &sw->ports, new_port ); }
OFDPE add_group_entry( group_entry *entry ) { assert( table != NULL ); if ( entry == NULL ) { return ERROR_INVALID_PARAMETER; } if ( !valid_group_id( entry->group_id ) ) { return ERROR_OFDPE_GROUP_MOD_FAILED_INVALID_GROUP; } if ( group_exists( entry->group_id ) ) { return ERROR_OFDPE_GROUP_MOD_FAILED_GROUP_EXISTS; } if ( !lock_pipeline() ) { return ERROR_LOCK; } OFDPE ret = validate_group_entry( entry ); if ( ret == OFDPE_SUCCESS ) { append_to_tail( &table->entries, entry ); } if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return ret; }
OFDPE delete_flow_entries_by_group_id( const uint32_t group_id ) { assert( valid_group_id( group_id ) ); if ( !lock_pipeline() ) { return ERROR_LOCK; } list_element *delete_us = NULL; create_list( &delete_us ); for ( uint8_t table_id = 0; table_id <= FLOW_TABLE_ID_MAX; table_id++ ) { flow_table *table = get_flow_table( table_id ); assert( table != NULL ); for ( list_element *e = table->entries; e != NULL; e = e->next ) { assert( e->data != NULL ); flow_entry *entry = e->data; if ( instructions_have_output_group( entry->instructions, group_id ) ) { append_to_tail( &delete_us, e->data ); } } } delete_flow_entries_in_list( delete_us, 0, 0, OFPP_ANY, OFPG_ANY, OFPRR_GROUP_DELETE ); if ( delete_us != NULL ) { delete_list( delete_us ); } if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return OFDPE_SUCCESS; }
static bool insert_wildcards_match_entry( list_element **wildcards_table, struct ofp_match *match, uint16_t priority, void *data ) { assert( match != NULL ); list_element *element; for ( element = *wildcards_table; element != NULL; element = element->next ) { match_entry *entry = element->data; if ( entry->priority < priority ) { break; } assert( entry != NULL ); if ( entry->priority == priority && compare_match_strict( &entry->match, match ) ) { char match_string[ MATCH_STRING_LENGTH ]; match_to_string( match, match_string, sizeof( match_string ) ); warn( "wildcards match entry already exists ( match = [%s], priority = %u )", match_string, priority ); return false; } } match_entry *new_entry = allocate_match_entry( match, priority, data ); if ( element == NULL ) { // tail append_to_tail( wildcards_table, new_entry ); } else if ( element == *wildcards_table ) { // head insert_in_front( wildcards_table, new_entry ); } else { // insert before insert_before( wildcards_table, element->data, new_entry ); } return true; }
static void append_switch_port_to_list( switch_port *port, void *user_data ) { assert( port != NULL ); assert( user_data != NULL ); list_element **ports = user_data; append_to_tail( ports, port ); }
static void append_switch_port_to_list( switch_port *port, void *user_data ) { assert( port != NULL ); assert( user_data != NULL ); switch_port_list *ports = user_data; if ( ports->in_port != port->port_no ) { append_to_tail( &ports->list, port ); } }
static bool set_match_type( int argc, char *argv[], services *services ) { create_list( &services->arp_or_unicast ); create_list( &services->broadcast ); int i; char *service_name; for ( i = 1; i < argc; i++ ) { if ( ( service_name = match_type( ARP_OR_UNICAST, argv[ i ] ) ) != NULL ) { append_to_tail( &services->arp_or_unicast, service_name ); } else if ( ( service_name = match_type( BROADCAST, argv[ i ] ) ) != NULL ) { append_to_tail( &services->broadcast, service_name ); } else { return false; } } return true; }
static bool append_oxm_match( oxm_matches *matches, oxm_match_header *entry ) { assert( matches != NULL ); assert( entry != NULL ); bool ret = append_to_tail( &matches->list, entry ); if ( ret ) { matches->n_matches++; } return ret; }
static void handle_ovs_flow_removed( uint64_t datapath_id, uint32_t transaction_id, const buffer *data ) { assert( data != NULL ); ovs_flow_removed *flow_removed = ( ovs_flow_removed * ) ( ( char * ) data->data - offsetof( ovs_header, subtype ) ); uint64_t cookie = ntohll( flow_removed->cookie ); uint16_t priority = ntohs( flow_removed->priority ); uint8_t reason = flow_removed->reason; uint32_t duration_sec = ntohl( flow_removed->duration_sec ); uint32_t duration_nsec = ntohl( flow_removed->duration_nsec ); uint16_t idle_timeout = ntohs( flow_removed->idle_timeout ); size_t match_length = ntohs( flow_removed->match_len ); uint64_t packet_count = ntohll( flow_removed->packet_count ); uint64_t byte_count = ntohll( flow_removed->byte_count ); ovs_matches *matches = create_ovs_matches(); size_t offset = sizeof( ovs_flow_removed ); while ( match_length >= sizeof( ovs_match_header ) ) { ovs_match_header *src = ( ovs_match_header * ) ( ( char * ) flow_removed + offset ); size_t length = get_ovs_match_length( ntohl( *src ) ) + sizeof( ovs_match_header ); ovs_match_header *dst = xmalloc( length ); ntoh_ovs_match( dst, src ); append_to_tail( &matches->list, dst ); matches->n_matches++; offset += length; match_length -= length; } char matches_str[ 256 ]; ovs_matches_to_string( matches, matches_str, sizeof( matches_str ) ); debug( "An Open vSwitch extended flow removed received ( datapath_id = %#" PRIx64 ", " "transaction_id = %#x, cookie = %#" PRIx64 ", priority = %u, reason = %#x, " "duration = %u.%09u, idle_timeout = %u, packet_count = %" PRIu64 ", byte_count = %" PRIu64 ", matches = [%s], user_data = %p ).", datapath_id, transaction_id, cookie, priority, reason, duration_sec, duration_nsec, idle_timeout, packet_count, byte_count, matches_str, event_handlers.ovs_flow_removed_user_data ); if ( event_handlers.ovs_flow_removed_callback != NULL ) { event_handlers.ovs_flow_removed_callback( datapath_id, transaction_id, cookie, priority, reason, duration_sec, duration_nsec, idle_timeout, packet_count, byte_count, matches, event_handlers.ovs_flow_removed_user_data ); } delete_ovs_matches( matches ); }
OFDPE get_port_description( const uint32_t port_no, port_description **descriptions, uint32_t *n_ports ) { assert( port_no > 0 || port_no == OFPP_ALL ); assert( descriptions != NULL ); assert( n_ports != NULL ); if ( !lock_mutex( &mutex ) ) { return ERROR_LOCK; } *n_ports = 0; *descriptions = NULL; list_element *ports = NULL; if ( port_no != OFPP_ALL ) { switch_port *port = lookup_switch_port( port_no ); if ( ports == NULL ) { return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK; } create_list( &ports ); append_to_tail( &ports, port ); } else { ports = get_all_switch_ports(); if ( ports == NULL ) { return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK; } } *n_ports = ( uint32_t ) list_length_of( ports ); size_t length = ( *n_ports ) * sizeof( port_description ); *descriptions = xmalloc( length ); memset( *descriptions, 0, length ); port_description *description = *descriptions; for ( list_element *e = ports; e != NULL; e = e->next ) { assert( e->data != NULL ); switch_port *port = e->data; assert( port->device != NULL ); // FIXME: we assume that "port_description" is the same structure as "struct ofp_port". switch_port_to_ofp_port( description, port ); description++; } if ( !unlock_mutex( &mutex ) ) { return ERROR_UNLOCK; } return OFDPE_SUCCESS; }
static void append_stat( const char *key, const uint64_t value, void *user_data ) { assert( key != NULL ); assert( user_data != NULL ); list_element **stats = user_data; stat_entry *entry = xmalloc( sizeof( stat_entry ) ); memset( entry, 0, sizeof( stat_entry ) ); memcpy( entry->key, key, sizeof( entry->key ) ); entry->value = htonll( value ); append_to_tail( stats, entry ); }
static OFDPE insert_flow_entry( flow_table *table, flow_entry *entry, const uint16_t flags ) { assert( table != NULL ); assert( entry != NULL ); list_element *element = table->entries; while( element != NULL ) { list_element *next = element->next; flow_entry *e = element->data; assert( e != NULL ); if ( e->priority < entry->priority ) { break; } if ( e->priority == entry->priority ) { if ( e->table_miss && !entry->table_miss ) { break; } if ( ( flags & OFPFF_CHECK_OVERLAP ) != 0 && compare_match( e->match, entry->match ) ) { return ERROR_OFDPE_FLOW_MOD_FAILED_OVERLAP; } if ( compare_match_strict( e->match, entry->match ) ) { if ( ( flags & OFPFF_RESET_COUNTS ) != 0 ) { entry->byte_count = e->byte_count; entry->packet_count = e->packet_count; } flow_table *table = get_flow_table( e->table_id ); assert( table != NULL ); delete_flow_entry_from_table( table, e, 0, false ); } } element = next; } if ( element == NULL ) { // tail append_to_tail( &table->entries, entry ); } else if ( element == table->entries ) { // head insert_in_front( &table->entries, entry ); } else { // insert before insert_before( &table->entries, element->data, entry ); } increment_active_count( table->features.table_id ); return OFDPE_SUCCESS; }
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 get_reflectors_to_update( list_element **reflectors_to_update, uint32_t vni ) { debug( "Retriving packet reflectors to update ( reflectors_to_update = %p, vni = %#x ).", reflectors_to_update, vni ); assert( db != NULL ); assert( reflectors_to_update != NULL ); MYSQL_RES *result = NULL; bool ret = execute_query( db, "select reflectors.uri from reflectors,overlay_networks " "where overlay_networks.reflector_group_id = reflectors.group_id and " "overlay_networks.slice_id = %u", vni ); if ( !ret ) { return false; } result = mysql_store_result( db ); if ( result == NULL ) { error( "Failed to retrieve result from database ( %s ).", mysql_error( db ) ); return false; } assert( mysql_num_fields( result ) == 1 ); if ( mysql_num_rows( result ) == 0 ) { error( "Failed to retrieve packet reflector configuration ( vni = %#x ).", vni ); mysql_free_result( result ); return false; } create_list( reflectors_to_update ); char *uri = NULL; MYSQL_ROW row; while ( ( row = mysql_fetch_row( result ) ) != NULL ) { uri = xstrdup( row[ 0 ] ); append_to_tail( reflectors_to_update, uri ); } if ( list_length_of( *reflectors_to_update ) == 0 ) { delete_list( *reflectors_to_update ); } mysql_free_result( result ); return true; }
void management_event_forward_entries_set( list_element **service_list, const event_forward_operation_request *request, size_t request_len ) { const size_t service_name_list_len = request_len - offsetof( event_forward_operation_request, service_list ); const char **service_name_list = xcalloc( request->n_services, sizeof( char * ) ); // split null terminated string list. unsigned int n_services = 0; const char *name_begin = request->service_list; for ( size_t i = 0 ; i < service_name_list_len ; ++i ) { if ( request->service_list[ i ] == '\0' ) { service_name_list[ n_services++ ] = name_begin; if ( n_services == request->n_services ) { if ( i + 1 != service_name_list_len ) { warn( "Expecting %d name(s) for EVENT_FWD_ENTRY_SET, but more exist. Ignoring.", request->n_services ); } break; } name_begin = &request->service_list[ i + 1 ]; } } if ( n_services != request->n_services ) { warn( "Expected %d name(s) for EVENT_FWD_ENTRY_SET, but found %d.", request->n_services, n_services ); } info( "Resetting event filter(s)." ); // clear current list iterate_list( *service_list, xfree_data, NULL ); delete_list( *service_list ); create_list( service_list ); // set new list for ( unsigned int i = 0 ; i < n_services ; ++i ) { const size_t service_name_len = strlen( service_name_list[ i ] ); if ( service_name_len == 0 ) { warn( "Ignoring 0 length service name in EVENT_FWD_ENTRY_SET" ); continue; } info( " Adding '%s' to event filter.", service_name_list[ i ] ); append_to_tail( service_list, xstrdup( service_name_list[ i ] ) ); } xfree( service_name_list ); }
/* * @!group Operation for existing switch * * @overload set_forward_entries_to_switch datapath_id, type, service_name, {|result, services| ... } * Set forwarding entries of a switch specified. * * @param [Integer] dpid Switch datapath_id * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify * @param [Array<String>] service_names Name of controller to forward event. * @return [Boolean] true if request was sent successfully. * * @yield Callback to notify the result of operation. * @yieldparam result [Boolean] true if result successful. * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation. */ static VALUE set_forward_entries_to_switch( VALUE self, VALUE dpid, VALUE type, VALUE service_names ) { debug( "%s", __func__ ); enum efi_event_type c_type; if ( !event_type_symbol_to_enum( type, &c_type ) ) { warn( "Invalid event type was specified" ); return Qfalse; } const uint64_t c_dpid = NUM2ULL( dpid ); list_element *service_list = NULL; create_list( &service_list ); for ( long i = 0 ; i < RARRAY( service_names )->len ; ++i ) { VALUE ruby_service_name = rb_ary_entry( service_names, i ); char *c_service_name = StringValuePtr( ruby_service_name ); if ( strlen( c_service_name ) == 0 ) { warn( "Ignoring empty service_name" ); continue; } append_to_tail( &service_list, c_service_name ); } callback_info *cb = xcalloc( 1, sizeof( callback_info ) ); cb->self = self; cb->block = Qnil; if ( rb_block_given_p() == Qtrue ) { cb->block = rb_block_proc(); } bool succ = set_switch_event_forward_entries( c_dpid, c_type, service_list, handle_event_forward_entry_operation_callback, cb ); delete_list( service_list ); if ( succ ) { return Qtrue; } else { xfree( cb ); return Qfalse; } }
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(); } }
OFDPE replace_meter_entry( const uint16_t flags, const uint32_t meter_id, const list_element *bands ) { assert( table != NULL ); if ( meter_id == 0 || ( meter_id > OFPM_MAX && meter_id != OFPM_CONTROLLER )) { return ERROR_OFDPE_METER_MOD_FAILED_INVALID_METER; } meter_entry *entry = alloc_meter_entry( flags, meter_id, bands ); if ( entry == NULL ) { return ERROR_INVALID_PARAMETER; } OFDPE ret = OFDPE_SUCCESS; if ( !lock_pipeline() ) { free_meter_entry( entry ); return ERROR_LOCK; } meter_entry *old_entry = lookup_meter_entry( entry->meter_id ); if ( NULL == old_entry ) { ret = ERROR_OFDPE_METER_MOD_FAILED_UNKNOWN_METER; free_meter_entry( entry ); } else { entry->ref_count = old_entry->ref_count; entry->packet_count = old_entry->packet_count; entry->byte_count = old_entry->byte_count; entry->estimated_rate = old_entry->estimated_rate; entry->created_at = old_entry->created_at; entry->meter_at = old_entry->meter_at; delete_element( &table->entries, old_entry ); append_to_tail( &table->entries, entry ); free_meter_entry( old_entry ); } if ( !unlock_pipeline() ) { free_meter_entry( entry ); return ERROR_UNLOCK; } return ret; }
void management_event_forward_entry_add( list_element **service_list, const event_forward_operation_request *request, size_t request_len ) { if ( request->n_services == 0 ) return; if ( request->n_services > 1 ) { warn( "Only 1 service name expected for EVENT_FWD_ENTRY_ADD. Ignoring others." ); } const size_t service_name_len = request_len - offsetof( event_forward_operation_request, service_list ); if ( service_name_len == 0 ) return; char *service_name = xcalloc( service_name_len + 1, sizeof( char ) ); strncpy( service_name, request->service_list, service_name_len ); const char *match = find_list_custom( *service_list, string_equal, service_name ); if ( match == NULL ) { info( "Adding '%s' to event filter.", service_name ); append_to_tail( service_list, service_name ); } else { // already there xfree( service_name ); } }
static void insert_data( list_element **head, const topology_link_status *s ) { list_element *element; for ( element = *head; element != NULL; element = element->next ) { const topology_link_status *entry = element->data; if ( entry->from_dpid > s->from_dpid ) { break; } if ( entry->from_dpid < s->from_dpid ) { continue; } if ( entry->from_portno > s->from_portno ) { break; } if ( entry->from_portno < s->from_portno ) { continue; } if ( entry->to_dpid > s->to_dpid ) { break; } if ( entry->to_dpid < s->to_dpid ) { continue; } if ( entry->to_portno > s->to_portno ) { break; } } if ( element == NULL ) { append_to_tail( head, ( void * ) ( intptr_t ) s ); } else if ( element == *head ) { insert_in_front( head, ( void * ) ( intptr_t ) s ); } else { insert_before( head, element->data, ( void * ) ( intptr_t ) s ); } }
static bool add_packetin_match_entry( struct ofp_match match, uint16_t priority, const char *service_name ) { bool ( *insert_or_update_match_entry )( struct ofp_match, uint16_t, void * ) = update_match_entry; list_element *services = lookup_match_strict_entry( match, priority ); if ( services == NULL ) { insert_or_update_match_entry = insert_match_entry; create_list( &services ); } else { list_element *element; for ( element = services; element != NULL; element = element->next ) { if ( strcmp( element->data, service_name ) == 0 ) { char match_string[ 256 ]; match_to_string( &match, match_string, sizeof( match_string ) ); warn( "match entry already exists ( match = [%s], service_name = [%s] )", match_string, service_name ); return false; } } } append_to_tail( &services, xstrdup( service_name ) ); insert_or_update_match_entry( match, priority, services ); return true; }
OFDPE get_flow_stats( const uint8_t table_id, const match *match, const uint64_t cookie, const uint64_t cookie_mask, const uint32_t out_port, const uint32_t out_group, flow_stats **stats, uint32_t *n_entries ) { assert( valid_table_id( table_id ) || table_id == FLOW_TABLE_ALL ); assert( stats != NULL ); assert( n_entries != NULL ); if ( !lock_pipeline() ) { return ERROR_LOCK; } list_element *list = NULL; if ( table_id != FLOW_TABLE_ALL ) { list = lookup_flow_entries_with_table_id( table_id, match, 0, false, false ); } else { list = lookup_flow_entries_from_all_tables( match, 0, false, false ); } *n_entries = 0; list_element *entries = NULL; create_list( &entries ); for ( list_element *e = list; e != NULL; e = e->next ) { flow_entry *entry = e->data; assert( entry != NULL ); bool matched = true; if ( out_port != OFPP_ANY ) { if ( !instructions_have_output_port( entry->instructions, out_port ) ) { matched = false; } } if ( out_group != OFPG_ANY ) { if ( !instructions_have_output_group( entry->instructions, out_group ) ) { matched = false; } } if ( matched && cookie_mask != 0 ) { if ( ( entry->cookie & cookie_mask ) != ( cookie & cookie_mask ) ) { matched = false; } } if ( matched ) { ( *n_entries )++; append_to_tail( &entries, entry ); } } if ( list != NULL ) { delete_list( list ); } *stats = NULL; if ( *n_entries > 0 ) { *stats = xmalloc( sizeof( flow_stats ) * ( *n_entries ) ); memset( *stats, 0, sizeof( flow_stats ) * ( *n_entries ) ); } struct timespec now = { 0, 0 }; time_now( &now ); struct timespec diff = { 0, 0 }; flow_stats *stat = *stats; for ( list_element *e = entries; e != NULL; e = e->next ) { flow_entry *entry = e->data; stat->table_id = entry->table_id; timespec_diff( entry->created_at, now, &diff ); stat->duration_sec = ( uint32_t ) diff.tv_sec; stat->duration_nsec = ( uint32_t ) diff.tv_nsec; stat->priority = entry->priority; stat->idle_timeout = entry->idle_timeout; stat->hard_timeout = entry->hard_timeout; stat->flags = entry->flags; stat->cookie = entry->cookie; stat->packet_count = entry->packet_count; stat->byte_count = entry->byte_count; stat->match = *entry->match; stat->instructions = *entry->instructions; stat++; } if ( entries != NULL ) { delete_list( entries ); } if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return OFDPE_SUCCESS; }
OFDPE get_port_stats( const uint32_t port_no, port_stats **stats, uint32_t *n_ports ) { assert( ( port_no > 0 && port_no <= OFPP_MAX ) || port_no == OFPP_ANY ); assert( stats != NULL ); assert( n_ports != NULL ); if ( !lock_mutex( &mutex ) ) { return ERROR_LOCK; } list_element *ports = NULL; *n_ports = 0; *stats = NULL; if ( port_no != OFPP_ANY ) { switch_port *port = lookup_switch_port( port_no ); if ( port == NULL ) { if ( unlock_mutex( &mutex ) != OFDPE_SUCCESS ) { return ERROR_UNLOCK; } return ERROR_OFDPE_BAD_REQUEST_BAD_PORT; } create_list( &ports ); append_to_tail( &ports, port ); } else { ports = get_all_switch_ports(); if ( ports == NULL ) { return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK; } } *n_ports = ( uint32_t ) list_length_of( ports ); size_t length = ( *n_ports ) * sizeof( port_stats ); *stats = xmalloc( length ); memset( *stats, 0, length ); port_stats *stat = *stats; for ( list_element *e = ports; e != NULL; e = e->next ) { assert( e->data != NULL ); switch_port *port = e->data; stat->port_no = port->port_no; assert( port->device != NULL ); stat->rx_packets = port->device->stats.rx_packets; stat->tx_packets = port->device->stats.tx_packets; stat->rx_bytes = port->device->stats.rx_bytes; stat->tx_bytes = port->device->stats.tx_bytes; stat->rx_dropped = port->device->stats.rx_dropped; stat->tx_dropped = port->device->stats.tx_dropped; stat->rx_errors = port->device->stats.rx_errors; stat->tx_errors = port->device->stats.tx_errors; stat->rx_frame_err = port->device->stats.rx_frame_err; stat->rx_over_err = port->device->stats.rx_over_err; stat->rx_crc_err = port->device->stats.rx_crc_err; stat->collisions = port->device->stats.collisions; struct timespec duration = get_switch_port_uptime( port ); stat->duration_sec = ( uint32_t ) duration.tv_sec; stat->duration_nsec = ( uint32_t ) duration.tv_nsec; stat++; } if ( !unlock_mutex( &mutex ) ) { return ERROR_UNLOCK; } return OFDPE_SUCCESS; }
static void append_physical_port( void *port, void *physical_ports ) { if ( ( ( struct ofp_phy_port * ) port )->port_no <= OFPP_MAX ) { append_to_tail( ( list_element ** ) physical_ports, port ); } }
OFDPE get_group_stats( const uint32_t group_id, group_stats **stats, uint32_t *n_groups ) { assert( table != NULL ); assert( stats != NULL ); assert( n_groups != NULL ); if ( !valid_group_id( group_id ) && group_id != OFPG_ALL ) { return ERROR_OFDPE_BAD_REQUEST_BAD_TABLE_ID; } if ( !lock_pipeline() ) { return ERROR_LOCK; } OFDPE ret = OFDPE_SUCCESS; list_element *groups = NULL; create_list( &groups ); *n_groups = 0; if ( group_id != OFPG_ALL ) { group_entry *entry = lookup_group_entry( group_id ); if ( entry == NULL ) { if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return ERROR_OFDPE_BAD_REQUEST_BAD_TABLE_ID; } append_to_tail( &groups, entry ); ( *n_groups )++; } else { for ( list_element *e = table->entries; e != NULL; e = e->next ) { if ( e->data == NULL ) { continue; } group_entry *entry = e->data; append_to_tail( &groups, entry ); ( *n_groups )++; } } *stats = NULL; if ( *n_groups > 0 ) { *stats = xmalloc( sizeof( group_stats ) * ( *n_groups ) ); memset( *stats, 0, sizeof( group_stats ) * ( *n_groups ) ); } group_stats *stat = *stats; for ( list_element *e = groups; e != NULL; e = e->next ) { assert( e->data != NULL ); group_entry *entry = e->data; stat->group_id = entry->group_id; stat->ref_count = entry->ref_count; stat->packet_count = entry->packet_count; stat->byte_count = entry->byte_count; struct timespec now = { 0, 0 }; time_now( &now ); struct timespec diff = { 0, 0 }; timespec_diff( entry->created_at, now, &diff ); stat->duration_sec = ( uint32_t ) diff.tv_sec; stat->duration_nsec = ( uint32_t ) diff.tv_nsec; create_list( &stat->bucket_stats ); for ( dlist_element *b = get_first_element( entry->buckets ); b != NULL; b = b->next ) { if ( b->data == NULL ) { continue; } bucket *bucket = b->data; bucket_counter *counter = xmalloc( sizeof( bucket_counter ) ); memset( counter, 0, sizeof( bucket_counter ) ); counter->packet_count = bucket->packet_count; counter->byte_count = bucket->byte_count; append_to_tail( &stat->bucket_stats, counter ); } stat++; } if ( groups != NULL ) { delete_list( groups ); } if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return ret; }
static bool parse_argument( int argc, char *argv[] ) { bool type_specified = false; create_list( &service_names ); int c; while ( ( c = getopt_long( argc, argv, short_options, long_options, NULL ) ) != -1 ) { switch ( c ) { case 'm': sw_manager = true; break; case 's': sw_manager = false; if ( !string_to_datapath_id( optarg, &dpid ) ) { error( "Invalid dpid '%s' specified. ", optarg ); usage(); exit( EXIT_FAILURE ); return false; } break; case 't': // add type_specified = true; if ( false ) { } else if ( strcasecmp( "vendor", optarg ) == 0 ) { type = EVENT_FORWARD_TYPE_VENDOR; } else if ( strcasecmp( "packet_in", optarg ) == 0 ) { type = EVENT_FORWARD_TYPE_PACKET_IN; } else if ( strcasecmp( "port_status", optarg ) == 0 ) { type = EVENT_FORWARD_TYPE_PORT_STATUS; } else if ( strcasecmp( "state_notify", optarg ) == 0 ) { type = EVENT_FORWARD_TYPE_STATE_NOTIFY; } else { error( "Invalid type '%s' specified. Must e one of vendor, packet_in, port_status, or state_notify\n", optarg ); usage(); exit( EXIT_FAILURE ); return false; } break; default: error( "Encountered unknown option." ); usage(); exit( EXIT_FAILURE ); return false; break; } } if ( !type_specified ) { error( "Event Type was not specified with -t option.\n" ); usage(); exit( EXIT_FAILURE ); return false; } if ( optind >= argc ) { error( "Service names were not specified.\n" ); usage(); exit( EXIT_FAILURE ); return false; } int i; for ( i = optind; i < argc; ++i ) { char *service_name = strtok( argv[ i ], "," ); if ( service_name != NULL ) { append_to_tail( &service_names, service_name ); while ( ( service_name = strtok( NULL, "," ) ) != NULL ) { append_to_tail( &service_names, service_name ); } } } return true; }