static void test_match_to_string_fails_with_insufficient_buffer() { char match_str[ 1 ]; struct ofp_match match; assert_false( match_to_string( &match, match_str, sizeof( match_str ) ) ); }
void match_print(const struct match *match) { char *s = match_to_string(match, OFP_DEFAULT_PRIORITY); puts(s); free(s); }
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 discard_packet_in( uint64_t datapath_id, uint16_t in_port, const buffer *packet ) { const uint32_t wildcards = 0; struct ofp_match match; set_match_from_packet( &match, in_port, wildcards, packet ); char match_str[ 1024 ]; match_to_string( &match, match_str, sizeof( match_str ) ); const uint16_t idle_timeout = 0; const uint16_t hard_timeout = PACKET_IN_DISCARD_DURATION; const uint16_t priority = UINT16_MAX; const uint32_t buffer_id = UINT32_MAX; const uint16_t flags = 0; info( "Discarding packets for a certain period ( datapath_id = %#" PRIx64 ", match = [%s], duration = %u [sec] ).", datapath_id, match_str, hard_timeout ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); }
/* * (see ActionEnqueue#to_s) */ static VALUE match_to_s( VALUE self ) { char match_str[ 1024 ]; match_to_string( get_match( self ), match_str, sizeof ( match_str ) ); return rb_str_new2( match_str ); }
/* Converts 'match' to a string and returns the string. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in the string. The caller * must free the string (with free()). */ char * minimatch_to_string(const struct minimatch *match, unsigned int priority) { struct match megamatch; minimatch_expand(match, &megamatch); return match_to_string(&megamatch, priority); }
void timeout( void *user_data ) { handler_data *data = user_data; char match_string[ 512 ]; match_to_string( &data->match, match_string, sizeof( match_string ) ); error( "Timeout ( match = [%s], service_name = %s, strict = %s ).", match_string, data->service_name, data->strict ? "true" : "false" ); stop_trema(); }
void dump_filters( int status, int n_entries, packetin_filter_entry *entries, void *user_data ) { handler_data *data = user_data; char match_string[ 512 ]; match_to_string( &data->match, match_string, sizeof( match_string ) ); if ( status != PACKETIN_FILTER_OPERATION_SUCCEEDED ) { error( "Failed to dump packetin filters ( match = [%s], service_name = %s, strict = %s ).", match_string, data->service_name, data->strict ? "true" : "false" ); } info( "%d packetin filter%s found ( match = [%s], service_name = %s, strict = %s ).", n_entries, n_entries > 1 ? "s" : "", match_string, data->service_name, data->strict ? "true" : "false" ); for ( int i = 0; i < n_entries; i++ ) { match_to_string( &entries[ i ].match, match_string, sizeof( match_string ) ); info( "[#%d] match = [%s], priority = %u, service_name = %s.", i, match_string, entries[ i ].priority, entries[ i ].service_name ); } stop_trema(); }
static void test_match_to_string() { char match_str[ 256 ]; char expected_match_str[] = "wildcards = 0(none), in_port = 1, dl_src = 01:02:03:04:05:07, dl_dst = 08:09:0a:0b:0c:0d, dl_vlan = 0x1, dl_vlan_pcp = 0x1, dl_type = 0x800, nw_tos = 1, nw_proto = 6, nw_src = 10.9.8.7/32, nw_dst = 6.5.4.3/32, tp_src = 1024, tp_dst = 2048"; struct ofp_match match = { 0, 1, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x07 }, { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, 1, 1, { 0 }, 0x800, 1, 0x6, { 0, 0 }, 0x0a090807, 0x06050403, 1024, 2048 }; assert_true( match_to_string( &match, match_str, sizeof( match_str ) ) ); assert_string_equal( match_str, expected_match_str ); }
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 ) { UNUSED( user_data ); char match_str[ 1024 ]; struct ofp_match ofp_match; // host order buffer *copy = NULL; packet_info *packet_info = data->user_data; debug( "Receive packet. ethertype=0x%04x, ipproto=0x%x", packet_info->eth_type, packet_info->ipv4_protocol ); if ( packet_type_ipv4_etherip( data ) ) { copy = parse_etherip( data ); } set_match_from_packet( &ofp_match, in_port, 0, copy != NULL ? copy : data ); if ( copy != NULL ) { free_buffer( copy ); copy = NULL; } match_to_string( &ofp_match, match_str, sizeof( match_str ) ); list_element *services = lookup_match_entry( ofp_match ); if ( services == NULL ) { debug( "match entry not found" ); 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 ); list_element *element; for ( element = services; element != NULL; element = element->next ) { const char *service_name = element->data; if ( !send_message( service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { error( "Failed to send a message to %s ( match = %s ).", service_name, match_str ); free_buffer( buf ); return; } debug( "Sending a message to %s ( match = %s ).", service_name, match_str ); } free_buffer( buf ); }
static void dump_filters( int status, int n_entries, packetin_filter_entry *entries, void *user_data ) { UNUSED( user_data ); if ( status != PACKETIN_FILTER_OPERATION_SUCCEEDED ) { error( "Failed to dump packetin filters." ); } info( "%d packetin filters found.", n_entries ); for ( int i = 0; i < n_entries; i++ ) { char match_string[ 256 ]; match_to_string( &entries[ i ].match, match_string, sizeof( match_string ) ); info( "match = [%s], priority = %u, service_name = %s.", match_string, entries[ i ].priority, entries[ i ].service_name ); } }
static bool update_wildcards_match_entry( list_element *wildcards_table, struct ofp_match *match, uint16_t priority, void *data ) { assert( match != NULL ); match_entry *entry = lookup_wildcards_match_strict_entry( wildcards_table, match, priority ); if ( entry == NULL ) { char match_string[ MATCH_STRING_LENGTH ]; match_to_string( match, match_string, sizeof( match_string ) ); warn( "wildcards match entry not found ( match = [%s], priority = %u )", match_string, priority ); return false; } entry->data = data; return true; }
void add_filter_completed( int status, void *user_data ) { handler_data *data = user_data; char match_string[ 512 ]; match_to_string( &data->match, match_string, sizeof( match_string ) ); if ( status != PACKETIN_FILTER_OPERATION_SUCCEEDED ) { error( "Failed to add a packetin filter ( match = [%s], service_name = %s ).", match_string, data->service_name ); } info( "A packetin filter was added ( match = [%s], service_name = %s ).", match_string, data->service_name ); stop_trema(); }
void delete_filter_completed( int status, int n_deleted, void *user_data ) { handler_data *data = user_data; char match_string[ 512 ]; match_to_string( &data->match, match_string, sizeof( match_string ) ); if ( status != PACKETIN_FILTER_OPERATION_SUCCEEDED ) { error( "Failed to delete packetin filters ( match = [%s], service_name = %s, strict = %s ).", match_string, data->service_name, data->strict ? "true" : "false" ); } info( "%d packetin filter%s deleted ( match = [%s], service_name = %s, strict = %s ).", n_deleted, n_deleted > 1 ? "s were" : " was", match_string, data->service_name, data->strict ? "true" : "false" ); stop_trema(); }
static bool update_exact_match_entry( hash_table *exact_table, struct ofp_match *match, void *data ) { assert( exact_table != NULL ); assert( match != NULL ); match_entry *entry = lookup_exact_match_strict_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 false; } entry->data = data; return true; }
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; }
static void handle_packet_in( uint64_t datapath_id, packet_in message ) { info( "received a packet_in" ); info( "datapath_id: %#" PRIx64, datapath_id ); info( "transaction_id: %#x", message.transaction_id ); info( "buffer_id: %#x", message.buffer_id ); info( "total_len: %u", message.total_len ); info( "reason: %#x", message.reason ); info( "table_id: %#x", message.table_id ); info( "cookie: %#" PRIx64, message.cookie ); char match_string[ MATCH_STRING_LENGTH ]; memset( match_string, '\0', MATCH_STRING_LENGTH ); match_to_string( message.match, match_string, sizeof( match_string ) ); info( "match: %s", match_string ); info( "data:" ); dump_buffer( message.data, info ); }
static void * delete_wildcards_match_strict_entry( list_element **wildcards_table, struct ofp_match *match, uint16_t priority ) { assert( match != NULL ); match_entry *entry = lookup_wildcards_match_strict_entry( *wildcards_table, match, priority ); if ( entry == NULL ) { char match_string[ MATCH_STRING_LENGTH ]; match_to_string( match, match_string, sizeof( match_string ) ); warn( "wildcards match entry not found ( match = [%s], priority = %u )", match_string, priority ); return NULL; } void *data = entry->data; delete_element( wildcards_table, entry ); free_match_entry( entry ); return data; }
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; }
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 ) { UNUSED( user_data ); char match_str[ 1024 ]; struct ofp_match ofp_match; // host order set_match_from_packet( &ofp_match, in_port, 0, data ); match_to_string( &ofp_match, match_str, sizeof( match_str ) ); match_entry *match_entry = lookup_match_entry( &ofp_match ); if ( match_entry == NULL ) { debug( "No match entry found." ); 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 ); if ( !send_message( match_entry->service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { error( "Failed to send a message to %s ( entry_name = %s, match = %s ).", match_entry->service_name, match_entry->entry_name, match_str ); free_buffer( buf ); return; } debug( "Sending a message to %s ( entry_name = %s, match = %s ).", match_entry->service_name, match_entry->entry_name, match_str ); free_buffer( buf ); }
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; }
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 ) { assert( in_port != 0 ); assert( data != NULL ); assert( user_data != NULL ); sliceable_switch *sliceable_switch = user_data; debug( "Packet-In received ( datapath_id = %#" PRIx64 ", transaction_id = %#lx, " "buffer_id = %#lx, total_len = %u, in_port = %u, reason = %#x, " "data_len = %u ).", datapath_id, transaction_id, buffer_id, total_len, in_port, reason, data->length ); if ( in_port > OFPP_MAX && in_port != OFPP_LOCAL ) { error( "Packet-In from invalid port ( in_port = %u ).", in_port ); return; } const port_info *port = lookup_port( sliceable_switch->switches, datapath_id, in_port ); if ( port == NULL ) { debug( "Ignoring Packet-In from unknown port." ); return; } packet_info packet_info = get_packet_info( data ); const uint8_t *src = packet_info.eth_macsa; const uint8_t *dst = packet_info.eth_macda; if ( !port->external_link || port->switch_to_switch_reverse_link ) { if ( !port->external_link && port->switch_to_switch_link && port->switch_to_switch_reverse_link && !is_ether_multicast( dst ) && lookup_fdb( sliceable_switch->fdb, src, &datapath_id, &in_port ) ) { debug( "Found a Packet-In from switch-to-switch link." ); } else { debug( "Ignoring Packet-In from non-external link." ); return; } } uint16_t vid = VLAN_NONE; if ( packet_type_eth_vtag( data ) ) { vid = packet_info.vlan_vid; } if ( !update_fdb( sliceable_switch->fdb, src, datapath_id, in_port ) ) { return; } char match_str[ 1024 ]; struct ofp_match match; set_match_from_packet( &match, in_port, 0, data ); match_to_string( &match, match_str, sizeof( match_str ) ); uint16_t slice = lookup_slice( datapath_id, in_port, vid, src ); if ( slice == SLICE_NOT_FOUND ) { warn( "No slice found ( dpid = %#" PRIx64 ", vid = %u, match = [%s] ).", datapath_id, vid, match_str ); goto deny; } int action = filter( datapath_id, in_port, slice, data ); switch ( action ) { case ALLOW: debug( "Filter: ALLOW ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto allow; case DENY: debug( "Filter: DENY ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto deny; case LOCAL: debug( "Filter: LOCAL ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto local; default: error( "Undefined filter action ( action = %#x ).", action ); goto deny; } allow: { uint16_t out_port; uint64_t out_datapath_id; if ( lookup_fdb( sliceable_switch->fdb, dst, &out_datapath_id, &out_port ) ) { // Host is located, so resolve path and send flowmod if ( ( datapath_id == out_datapath_id ) && ( in_port == out_port ) ) { debug( "Input port and out port are the same ( datapath_id = %#llx, port = %u ).", datapath_id, in_port ); return; } uint16_t out_vid = vid; bool found = get_port_vid( slice, out_datapath_id, out_port, &out_vid ); if ( found == false ) { uint16_t out_slice = lookup_slice_by_mac( dst ); if ( out_slice != slice ) { debug( "Destination is on different slice ( slice = %#x, out_slice = %#x ).", slice, out_slice ); goto deny; } } make_path( sliceable_switch, datapath_id, in_port, vid, out_datapath_id, out_port, out_vid, data ); } else { if ( lookup_path( datapath_id, match, PRIORITY ) != NULL ) { teardown_path( datapath_id, match, PRIORITY ); } // Host's location is unknown, so flood packet flood_packet( datapath_id, in_port, slice, data, sliceable_switch->switches ); } return; } deny: { // Drop packets for a certain period buffer *flow_mod = create_flow_mod( transaction_id, match, get_cookie(), OFPFC_ADD, 0, FLOW_TIMER, UINT16_MAX, UINT32_MAX, OFPP_NONE, 0, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); return; } local: { // Redirect to controller's local IP stack redirect( datapath_id, in_port, data ); return; } }
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 ); } }