void pa_policy_context_add_property_action(struct pa_policy_context_rule *rule, int lineno, enum pa_policy_object_type obj_type, enum pa_classify_method obj_classify, const char *obj_name, const char *prop_name, enum pa_policy_value_type value_type, ... /* value_arg */) { union pa_policy_context_action *action; struct pa_policy_set_property *setprop; va_list value_arg; action = pa_xmalloc0(sizeof(*action)); setprop = &action->setprop; setprop->type = pa_policy_set_property; setprop->lineno = lineno; setprop->object.type = obj_type; match_setup(&setprop->object.match, obj_classify, obj_name, NULL); setprop->property = pa_xstrdup(prop_name); va_start(value_arg, value_type); value_setup(&setprop->value, value_type, value_arg); va_end(value_arg); append_action(&rule->actions, action); }
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 void form_actions( VALUE raction, openflow_actions *actions ) { if ( raction != Qnil ) { switch ( TYPE( raction ) ) { case T_ARRAY: { VALUE *each = RARRAY_PTR( raction ); int i; for ( i = 0; i < RARRAY_LEN( raction ); i++ ) { append_action( actions, each[ i ] ); } } break; case T_OBJECT: append_action( actions, raction ); break; default: rb_raise( rb_eTypeError, "actions argument must be an Array or an Action object" ); } } }
void pa_policy_context_set_default_action(struct pa_policy_context_rule *rule, int lineno, struct userdata *u, const char *activity_group, int default_state) { union pa_policy_context_action *action; struct pa_policy_set_default *setdef; action = pa_xmalloc0(sizeof(*action)); setdef = &action->setdef; setdef->type = pa_policy_set_default; setdef->lineno = lineno; pa_assert_se((setdef->var = get_activity_variable(u, u->context, activity_group))); setdef->default_state = default_state; append_action(&rule->actions, action); }
void pa_policy_context_delete_property_action(struct pa_policy_context_rule *rule, int lineno, enum pa_policy_object_type obj_type, enum pa_classify_method obj_classify, const char *obj_name, const char *prop_name) { union pa_policy_context_action *action; struct pa_policy_del_property *delprop; action = pa_xmalloc0(sizeof(*action)); delprop = &action->delprop; delprop->type = pa_policy_delete_property; delprop->lineno = lineno; delprop->object.type = obj_type; match_setup(&delprop->object.match, obj_classify, obj_name, NULL); delprop->property = pa_xstrdup(prop_name); append_action(&rule->actions, action); }
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; }
int rewrite_rule_compile( struct rewrite_info *info, struct rewrite_context *context, const char *pattern, const char *result, const char *flagstring ) { int flags = REWRITE_REGEX_EXTENDED | REWRITE_REGEX_ICASE; int mode = REWRITE_RECURSE; int max_passes = info->li_max_passes_per_rule; struct rewrite_rule *rule = NULL; struct rewrite_subst *subst = NULL; struct rewrite_action *action = NULL, *first_action = NULL; const char *p; assert( info != NULL ); assert( context != NULL ); assert( pattern != NULL ); assert( result != NULL ); /* * A null flagstring should be allowed */ /* * Take care of substitution string */ subst = rewrite_subst_compile( info, result ); if ( subst == NULL ) { return REWRITE_ERR; } /* * Take care of flags */ for ( p = flagstring; p[ 0 ] != '\0'; p++ ) { switch( p[ 0 ] ) { /* * REGEX flags */ case REWRITE_FLAG_HONORCASE: /* 'C' */ /* * Honor case (default is case insensitive) */ flags &= ~REWRITE_REGEX_ICASE; break; case REWRITE_FLAG_BASICREGEX: /* 'R' */ /* * Use POSIX Basic Regular Expression syntax * instead of POSIX Extended Regular Expression * syntax (default) */ flags &= ~REWRITE_REGEX_EXTENDED; break; /* * Execution mode flags */ case REWRITE_FLAG_EXECONCE: /* ':' */ /* * Apply rule once only */ mode &= ~REWRITE_RECURSE; mode |= REWRITE_EXEC_ONCE; break; /* * Special action flags */ case REWRITE_FLAG_STOP: /* '@' */ /* * Bail out after applying rule */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } action->la_type = REWRITE_ACTION_STOP; break; case REWRITE_FLAG_UNWILLING: /* '#' */ /* * Matching objs will be marked as gone! */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } mode &= ~REWRITE_RECURSE; mode |= REWRITE_EXEC_ONCE; action->la_type = REWRITE_ACTION_UNWILLING; break; case REWRITE_FLAG_GOTO: /* 'G' */ /* * After applying rule, jump N rules */ case REWRITE_FLAG_USER: { /* 'U' */ /* * After applying rule, return user-defined * error code */ char *next = NULL; int *d; if ( p[ 1 ] != '{' ) { goto fail; } d = malloc( sizeof( int ) ); if ( d == NULL ) { goto fail; } d[ 0 ] = strtol( &p[ 2 ], &next, 0 ); if ( next == &p[ 2 ] || next[0] != '}' ) { free( d ); goto fail; } action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { free( d ); goto fail; } switch ( p[ 0 ] ) { case REWRITE_FLAG_GOTO: action->la_type = REWRITE_ACTION_GOTO; break; case REWRITE_FLAG_USER: action->la_type = REWRITE_ACTION_USER; break; default: assert(0); } action->la_args = (void *)d; p = next; /* p is incremented by the for ... */ break; } case REWRITE_FLAG_MAX_PASSES: { /* 'U' */ /* * Set the number of max passes per rule */ char *next = NULL; if ( p[ 1 ] != '{' ) { goto fail; } max_passes = strtol( &p[ 2 ], &next, 0 ); if ( next == &p[ 2 ] || next[0] != '}' ) { goto fail; } if ( max_passes < 1 ) { /* FIXME: nonsense ... */ max_passes = 1; } p = next; /* p is incremented by the for ... */ break; } case REWRITE_FLAG_IGNORE_ERR: /* 'I' */ /* * Ignore errors! */ action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { goto fail; } action->la_type = REWRITE_ACTION_IGNORE_ERR; break; /* * Other flags ... */ default: /* * Unimplemented feature (complain only) */ break; } /* * Stupid way to append to a list ... */ if ( action != NULL ) { append_action( &first_action, action ); action = NULL; } } /* * Finally, rule allocation */ rule = calloc( sizeof( struct rewrite_rule ), 1 ); if ( rule == NULL ) { goto fail; } /* * REGEX compilation (luckily I don't need to take care of this ...) */ if ( regcomp( &rule->lr_regex, ( char * )pattern, flags ) != 0 ) { goto fail; } /* * Just to remember them ... */ rule->lr_pattern = strdup( pattern ); rule->lr_subststring = strdup( result ); rule->lr_flagstring = strdup( flagstring ); if ( rule->lr_pattern == NULL || rule->lr_subststring == NULL || rule->lr_flagstring == NULL ) { goto fail; } /* * Load compiled data into rule */ rule->lr_subst = subst; /* * Set various parameters */ rule->lr_flags = flags; /* don't really need any longer ... */ rule->lr_mode = mode; rule->lr_max_passes = max_passes; rule->lr_action = first_action; /* * Append rule at the end of the rewrite context */ append_rule( context, rule ); return REWRITE_SUCCESS; fail: if ( rule ) { if ( rule->lr_pattern ) free( rule->lr_pattern ); if ( rule->lr_subststring ) free( rule->lr_subststring ); if ( rule->lr_flagstring ) free( rule->lr_flagstring ); free( rule ); } destroy_actions( first_action ); free( subst ); return REWRITE_ERR; }
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 ); } }
/** * Initialization code with parameters * @param ctx */ int init(struct oflops_context *ctx, char * config_str) { char *pos = NULL; char *param = config_str; int len = strlen(config_str); char *value = NULL; char *action; struct ofp_action_output *act_out; //init counters finished = 0; struct timeval now; gettimeofday(&now, NULL); cli_param = strdup(config_str); while(*config_str == ' ') { config_str++; } param = config_str; while(1) { pos = index(param, ' '); if((pos == NULL)) { if (*param != '\0') { pos = param + strlen(param) + 1; } else break; } *pos='\0'; pos++; value = index(param,'='); *value = '\0'; value++; //fprintf(stderr, "param = %s, value = %s\n", param, value); if(value != NULL) { if(strcmp(param, "pkt_size") == 0) { //parse int to get pkt size pkt_size = strtol(value, NULL, 0); if((pkt_size < MIN_PKT_SIZE) && (pkt_size > MAX_PKT_SIZE)) perror_and_exit("Invalid packet size value", 1); } else if(strcmp(param, "data_rate") == 0) { //parse int to get rate of background data datarate = strtol(value, NULL, 0); if((datarate < 0) || (datarate > 1010)) perror_and_exit("Invalid data rate param(Values between 1 and 1010)", 1); } else if(strcmp(param, "probe_rate") == 0) { //parse int to get measurement probe rate proberate = strtol(value, NULL, 0); if((proberate <= 0) || (proberate >= 1010)) perror_and_exit("Invalid probe rate param(Value between 1 and 1010)", 1); } else if(strcmp(param, "action") == 0) { char *p = value; while((*p != ' ') && (*p != '\0') && (config_str + len > p)) { action = p; //find where value ends and set it to null to extract the string. p = index(p, ','); if(p == NULL) { p = config_str + len + 1; *p='\0'; } else { *p = '\0'; p++; } //set null char to split action param and action value param = index(action, '/'); if(param != NULL) { *param = '\0'; param++; } //check if action value is correct and append it at the end of the action list if(*action >= '0' && *action <= '9') { append_action((*action) - '0', param); } else if (*action == 'a') { append_action(10, param); } else { printf("invalid action: %1s", action); continue; } } } else if(strcmp(param, "table") == 0) { //parse int to get pkt size table = strtol(value, NULL, 0); if((table < 0) && (table > 2)) perror_and_exit("Invalid table number", 1); } else if(strcmp(param, "flows") == 0) { //parse int to get pkt size flows = strtol(value, NULL, 0); if(flows <= 0) perror_and_exit("Invalid flow number", 1); } else fprintf(stderr, "Invalid parameter:%s\n", param); param = pos; } } //calculate sendind interval if(datarate > 0) { data_snd_interval = (pkt_size * byte_to_bits * sec_to_usec) / (datarate * mbits_to_bits); fprintf(stderr, "Sending data interval : %u usec (pkt_size: %u bytes, rate: %u Mbits/sec )\n", (uint32_t)data_snd_interval, (uint32_t)pkt_size, (uint32_t)datarate); } else { fprintf(stderr, "background data probe is disabled\n"); data_snd_interval = 0; } probe_snd_interval = (pkt_size * byte_to_bits * sec_to_usec) / (proberate * mbits_to_bits); fprintf(stderr, "Sending probe interval : %u usec (pkt_size: %u bytes, rate: %u Mbits/sec )\n", (uint32_t)probe_snd_interval, (uint32_t)pkt_size, (uint32_t)proberate); //by default the new rule should be redirected to port 2 to make the measurement easier /* fprintf(stderr, "by default output packet to port 1\n"); */ /* command_len += sizeof(struct ofp_action_output); */ /* command = realloc(command, command_len); */ /* act_out = (struct ofp_action_output *) */ /* (command + (command_len - sizeof(struct ofp_action_output))); */ /* act_out->type = htons(0); */ /* act_out->len = htons(8); */ /* act_out->max_len = htons(0); */ /* act_out->port = htons(ctx->channels[OFLOPS_DATA3].of_port); */ return 0; }