static void handle_flow_mod_mod( const uint32_t transaction_id, const uint64_t cookie, const uint64_t cookie_mask, const uint8_t table_id, const uint16_t idle_timeout, const uint16_t hard_timeout, const uint16_t priority, const uint32_t buffer_id, const uint16_t flags, const oxm_matches *oxm, const openflow_instructions *instructions, const bool strict, struct protocol *protocol ) { match *match = create_match( ); if ( oxm != NULL && oxm->n_matches > 0 ) { for ( list_element *e = oxm->list; e != NULL; e = e->next ) { oxm_match_header *hdr = e->data; assign_match( match, hdr ); } } instruction_set *ins_set = create_instruction_set(); if ( instructions != NULL ) { OFDPE ret = assign_instructions( ins_set, instructions->list ); if ( ret != OFDPE_SUCCESS ) { send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPBIC_UNSUP_INST ); delete_instruction_set( ins_set ); delete_match( match ); return; } } OFDPE ret = update_or_add_flow_entry( table_id, match, cookie, cookie_mask, priority, idle_timeout, hard_timeout, flags, strict, ins_set ); delete_instruction_set( ins_set ); delete_match( match ); if ( ret != OFDPE_SUCCESS ) { uint16_t type = OFPET_FLOW_MOD_FAILED; uint16_t code = OFPFMFC_UNKNOWN; get_ofp_error( ret, &type, &code ); send_error_message( transaction_id, type, code ); return; } if ( buffer_id != OFP_NO_BUFFER ) { action_list *actions = create_action_list(); action *action = create_action_output( OFPP_TABLE, UINT16_MAX ); append_action( actions, action ); ret = execute_packet_out( buffer_id, 0, actions, NULL ); delete_action_list( actions ); if ( ret != OFDPE_SUCCESS ) { uint16_t type = OFPET_FLOW_MOD_FAILED; uint16_t code = OFPFMFC_UNKNOWN; get_ofp_error( ret, &type, &code ); send_error_message( transaction_id, type, code ); return; } wakeup_datapath( protocol ); } }
static action_list * complete_action_list( void ) { action_list *ac_list = init_action_list(); // expect_value( mock_is_valid_port_no, port_no, PORT_NO ); action *ac_output = create_action_output( PORT_NO, MAX_LEN ); append_action( ac_list, ac_output ); const uint32_t group_id = GROUP_ID; action *ac_group = create_action_group( group_id ); append_action( ac_list, ac_group ); const uint32_t queue_id = QUEUE_ID; action *ac_set_queue = create_action_set_queue( queue_id ); append_action( ac_list, ac_set_queue ); const uint8_t mpls_ttl = MPLS_TTL; action *ac_set_mpls_ttl = create_action_set_mpls_ttl( mpls_ttl ); append_action( ac_list, ac_set_mpls_ttl ); action *ac_dec_mpls_ttl = create_action_dec_mpls_ttl(); append_action( ac_list, ac_dec_mpls_ttl ); const uint8_t nw_ttl = NW_TTL; action *ac_set_ipv4_ttl = create_action_set_ipv4_ttl( nw_ttl ); append_action( ac_list, ac_set_ipv4_ttl ); action *ac_dec_ipv4_ttl = create_action_dec_ipv4_ttl(); append_action( ac_list, ac_dec_ipv4_ttl ); action *ac_copy_ttl_out = create_action_copy_ttl_out(); append_action( ac_list, ac_copy_ttl_out ); action *ac_copy_ttl_in = create_action_copy_ttl_in(); append_action( ac_list, ac_copy_ttl_in ); const uint16_t ether_type = VLAN_ETHERTYPE; action *ac_action_push_vlan = create_action_push_vlan( ether_type ); append_action( ac_list, ac_action_push_vlan ); const uint16_t mpls_type = MPLS_ETHERTYPE; action *ac_action_push_mpls = create_action_push_mpls( mpls_type ); append_action( ac_list, ac_action_push_mpls ); const uint16_t pbb_type = PBB_ETHERTYPE; action *ac_action_push_pbb = create_action_push_pbb( pbb_type ); append_action( ac_list, ac_action_push_pbb ); action *ac_action_pop_vlan = create_action_pop_vlan(); append_action( ac_list, ac_action_pop_vlan ); action *ac_action_pop_mpls = create_action_pop_mpls( mpls_type ); append_action( ac_list, ac_action_pop_mpls ); action *ac_action_pop_pbb = create_action_pop_pbb(); append_action( ac_list, ac_action_pop_pbb ); match *match = init_match(); action *ac_action_set_field = create_action_set_field( match ); append_action( ac_list, ac_action_set_field ); return ac_list; }
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 ); } }