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 );
  }
}
Exemple #3
0
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;
}
Exemple #7
0
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 );
  }
}
Exemple #9
0
/**
 * 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;
}