Esempio n. 1
0
int oflops_get_channel_raw_fd(struct oflops_context * ctx, oflops_channel_name ch)
{
	struct ifreq ifr;
	struct sockaddr_ll saddrll;
	struct channel_info * ch_info;
	if(ch >= ctx->n_channels)
		return -1;	// no such channel
	ch_info = &ctx->channels[ch];
	if(ch_info->raw_sock != -1)	// already allocated?
		return ch_info->raw_sock;
	// else, setup raw socket
	ch_info->raw_sock = socket(AF_PACKET,SOCK_RAW, htons(ETH_P_ALL));
	if( ch_info->raw_sock == -1)
		perror_and_exit("raw socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))",1);
	// bind to a specific port
	strncpy(ifr.ifr_name,ch_info->dev,IFNAMSIZ);
	if( ioctl( ch_info->raw_sock, SIOCGIFINDEX, &ifr)  == -1 )
		perror_and_exit("ioctl()",1);
	memset(&saddrll, 0, sizeof(saddrll));
	saddrll.sll_family = AF_PACKET;
	saddrll.sll_protocol = ETH_P_ALL;
	saddrll.sll_ifindex = ifr.ifr_ifindex;
	if ( bind(ch_info->raw_sock, (struct sockaddr *) &saddrll, sizeof(struct sockaddr_ll)) == -1 )
		perror_and_exit("bind()",1);
	return ch_info->raw_sock;
}
Esempio n. 2
0
int make_sockaddr(unsigned char addr_type, address_union *address, unsigned int port,
			struct sockaddr **addr_p, socklen_t *addr_len_p) {
	switch (addr_type) {
		case ATYP_IPV4: {
			struct sockaddr_in *connect_sin = malloc(sizeof(struct sockaddr_in));
			if (connect_sin == NULL) perror_and_exit("malloc");
			memset(connect_sin, 0, sizeof(struct sockaddr_in));
			connect_sin->sin_family = AF_INET;
			connect_sin->sin_port = htons(port);
			memcpy(&(connect_sin->sin_addr.s_addr), address->ipv4, 4);
			*addr_p = (struct sockaddr *)connect_sin;
			*addr_len_p = sizeof(struct sockaddr_in);
			break;
		}
		case ATYP_IPV6: {
			struct sockaddr_in6 *connect_sin6 = malloc(sizeof(struct sockaddr_in6));
			if (connect_sin6 == NULL) perror_and_exit("malloc");
			memset(connect_sin6, 0, sizeof(struct sockaddr_in6));
			connect_sin6->sin6_family = AF_INET6;
			connect_sin6->sin6_port = htons(port);
			memcpy(&(connect_sin6->sin6_addr.s6_addr), address->ipv6, 16);
			*addr_p = (struct sockaddr *)connect_sin6;
			*addr_len_p = sizeof(struct sockaddr_in6);
			break;
		}
		case ATYP_DOMAIN: {
			char port_str[6]; // max len = 5 (for 65535) +1 for ending '\0'
			int printed = snprintf(port_str, sizeof(port_str), "%u", port);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
			assert(printed > 0 && printed < sizeof(port_str));
#pragma GCC diagnostic pop
			(void)printed;
			struct addrinfo hints;
			memset(&hints, 0, sizeof(hints));
			hints.ai_family = AF_UNSPEC;
			struct addrinfo *res;
			int ret = getaddrinfo(address->domain_name, port_str, &hints, &res);
			if (ret == EAI_NONAME || ret == EAI_NODATA ) return REP_HOST_UNREACHABLE;
			else if (ret != 0) printf_and_exit("getaddrinfo: %s", gai_strerror(ret));
			
			unsigned int addr_len = res->ai_addrlen;
			struct sockaddr *addr = malloc(addr_len);
			if (addr == NULL) perror_and_exit("malloc");
			memcpy(addr, res->ai_addr, addr_len);
			freeaddrinfo(res);
			*addr_p = addr;
			*addr_len_p = addr_len;
			break;
		}
	}
	return 0;
}
void Request::connect_server(bool is_nonblocking){
    /* connect server */
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if( server_fd < 0 )
        perror_and_exit("create socket error");
    if( socket_connect(server_fd, addr) < 0 )
        perror_and_exit(("connect to " + addr.ipv4_addr_str + ":" + std::to_string(addr.port_hbytes) + " error").c_str());
    is_server_connect = true;

    if( is_nonblocking ){
        int flags = fcntl(server_fd, F_GETFL, 0);
        fcntl(server_fd, F_SETFL, flags | O_NONBLOCK);
    }
}
Esempio n. 4
0
void setup_server_socket(global_config_struct *global_config, global_resources_struct *global_resources) {
	server_bind_addr_struct *server_bind_addr = &global_config->server_bind_addr;
	struct sockaddr_storage *addr = &server_bind_addr->addr;
	socklen_t addr_len = server_bind_addr->addr_len;

	int server_sockfd = socket(addr->ss_family, SOCK_STREAM, 0);
	if (server_sockfd < 0) perror_and_exit("socket");
	
	int yes = 1;
	if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) perror_and_exit("setsockopt");
	
	if (bind(server_sockfd, (struct sockaddr *)addr, addr_len)) perror_and_exit("bind");
	
	global_resources->server_sockfd = server_sockfd;
}
Esempio n. 5
0
/*
 * Initializes the logging system of oflops.
 * @param filename The file where the logging messages are stored. 
 */
void
oflops_log_init(const char *filename) {
  logger = fopen(filename, "w");
  if(logger == NULL) {
    perror_and_exit("failed to open log file", 1);
  }
}
Esempio n. 6
0
socketfd_t bind_and_listen_tcp_socket(SocketAddr& listen_addr){
    /* bind and listen tcp socket with listen_addr */
    socketfd_t listen_socket;
    listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if( listen_socket < 0 )
        perror_and_exit("create socket error");

    // int on = 1;
    // setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));

    if( socket_bind(listen_socket, listen_addr) < 0 )
        perror_and_exit("bind error");
    if( listen(listen_socket, 1) < 0)
        perror_and_exit("listen error");

    return listen_socket;
}
void Request::open_batch_file(){
    /* open batch_file */
    batch_file_stream.open(batch_file, std::fstream::in);
    if( !batch_file_stream ){
        perror_and_exit(("open batch_file " + batch_file + " error").c_str());
    }

    is_batch_file_open = true;
}
Esempio n. 8
0
/**********************************************************************
 * hook for the test module to get access to a udp file descriptor bound
 * 	to the data channel's device
 **/
int oflops_get_channel_fd(struct oflops_context * ctx, oflops_channel_name ch)
{
	struct ifreq ifr;
	struct channel_info * ch_info;
	if(ch >= ctx->n_channels)
		return -1;	// no such channel
	ch_info = &ctx->channels[ch];
	if(ch_info->sock != -1)	// already allocated?
		return ch_info->sock;
	// else, setup raw socket
	ch_info->sock = socket(AF_INET,SOCK_DGRAM,0);	// UDP socket
	if( ch_info->sock == -1)
		perror_and_exit("udp socket(AF_INET,SOCK_DGRAM,0)",1);
	// bind to a specific port
	strncpy(ifr.ifr_name,ch_info->dev,IFNAMSIZ);
	if( ioctl( ch_info->sock, SIOCGIFINDEX, &ifr)  == -1 )
		perror_and_exit("ioctl() bind to dev",1);
	return ch_info->sock;
}
Esempio n. 9
0
ssize_t write_wrapper(int fd, const void *buf, size_t count) {
	ssize_t write_bytes = write(fd, buf, count);
	if (write_bytes < 0) {
		if (errno == ECONNRESET) return -1;
		else perror_and_exit("write");
	}
	if (write_bytes == 0) return -1;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
	assert(write_bytes <= count);
#pragma GCC diagnostic pop
	return write_bytes;
}
Esempio n. 10
0
ssize_t read_wrapper(int fd, void *buf, size_t count) {
	ssize_t read_bytes = read(fd, buf, count);
	if (read_bytes < 0) {
		if (errno == ECONNRESET) return -1;
		else perror_and_exit("read");
	}
	if (read_bytes == 0) return -1;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
	assert(read_bytes <= count);
#pragma GCC diagnostic pop
	return read_bytes;
}
bool Request::send_batch_file_data_to_server_once(){
    if( !is_batch_file_open )
        return false;
    if( !is_server_connect )
        return false;

    std::string command;
    if( std::getline(batch_file_stream, command) ){
        command += "\n";
        int w_size = write_all(server_fd, command.c_str(), command.length());
        if( w_size < 0 ){
            perror_and_exit("write error");
        }
        nl2br(command);
        print_html_content(id, "<b>" + command + "</b>");
        return true;
    }
    batch_file_stream.close();
    is_batch_file_open = false;
    return false;
}
Esempio n. 12
0
void everror_and_exit(const char *s) {
	perror_and_exit(s);
}
Esempio n. 13
0
void process_args(int argc, char* argv[], global_config_struct *global_config) {
	cmdline_args_struct args_;
	cmdline_args_struct *args = &args_;
	parse_args(argc, argv, args);
	
	in_port_t port;
	{
		if (args->bind_port != NULL) {
			int p = atoi(args->bind_port);
			if (p <= 0 || p >= LARGE_PORT_NUMBER)
				printf_and_exit("invalid port");
			else
				port = (in_port_t)p;
		} else {
			port = default_bind_port;
		}
	}
	
	{
		server_bind_addr_struct *server_bind_addr = &global_config->server_bind_addr;
		
		assert(args->bind_ipv4 == NULL || args->bind_ipv6 == NULL);
		if (args->bind_ipv6 != NULL) {
			assert(sizeof(server_bind_addr->addr) >= sizeof(struct sockaddr_in6));
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&server_bind_addr->addr;
			memset(sin6, 0, sizeof(struct sockaddr_in6));
			sin6->sin6_family = AF_INET6;
			sin6->sin6_port = htons(port);
			int ret = inet_pton(AF_INET6, args->bind_ipv6, &sin6->sin6_addr);
			if (ret < 0) perror_and_exit("inet_pton");
			else if (ret != 1) printf_and_exit("invalid ipv6 address");
			
			server_bind_addr->addr_len = sizeof(struct sockaddr_in6);
		} else {
			assert(sizeof(server_bind_addr->addr) >= sizeof(struct sockaddr_in));
			struct sockaddr_in *sin = (struct sockaddr_in *)&server_bind_addr->addr;
			sin->sin_family = AF_INET;
			sin->sin_port = htons(port);
			if (args->bind_ipv4 == NULL) {
				sin->sin_addr.s_addr = htonl(default_bind_addr);
			} else {
				if (!inet_aton(args->bind_ipv4, &sin->sin_addr)) printf_and_exit("invalid ip address");
			}
			
			server_bind_addr->addr_len = sizeof(struct sockaddr_in);
		}
	}
	
	size_t transfer_buffer_size;
	{
		if (args->transfer_buffer_size != NULL) {
			long long int size = atoll(args->transfer_buffer_size);
			if (size <= 0)
				printf_and_exit("invalid transfer buffer size");
			else if (size == LONG_MAX || size > SSIZE_MAX)
				printf_and_exit("too large transfer buffer size");
			else
				transfer_buffer_size = (size_t)size;
		} else {
			transfer_buffer_size = default_transfer_buffer_size;
		}
	}
	global_config->transfer_buffer_size = transfer_buffer_size;
}
Esempio n. 14
0
void listen_server_socket(global_resources_struct *global_resources) {
	if (listen(global_resources->server_sockfd, MAXPENDING)) perror_and_exit("listen");
}
int main(int argc, char *argv[]){
    /*
     * 1. parse env QUERY_STRING
     * 2. check connection_server
     * 3. connect to server, and print response
     *    3.1. connect to server (non-blocking)
     *    3.2. read data from batch file, and send data as input to server
     *    3.3. get response from server, and print as html_version to stdout
     */

    std::map<std::string, std::string> query_parameters;
    query_parameters = cgi::http_get_parameters();

    std::vector<Request> all_requests;
    for( int i = 1; i <= 5; i++ ){
        std::string host_name = "h" + std::to_string(i);
        std::string port_name = "p" + std::to_string(i);
        std::string batch_file_name = "f" + std::to_string(i);
        if( query_parameters.count(host_name) > 0 ){
            std::string host = query_parameters[host_name];
            int port = std::stoi(query_parameters[port_name]);
            std::string batch_file = query_parameters[batch_file_name];

            all_requests.emplace_back(host, port, batch_file, all_requests.size());
        }
    }

    std::fstream err_log;
    err_log.open("cgi_error.log", std::fstream::out);
    for( const auto& req: all_requests ){
        err_log << req.addr.ipv4_addr_str << std::endl;
        err_log << req.addr.port_hbytes << std::endl;
        err_log << req.batch_file << std::endl;
    }

    /* part3 */
    /* initialization of every Request
     * 1. make an connection
     * 2. open batch_file
     */

#if 0
    // single connection
    Request req = all_requests[0];

    req.connect_server(false);
    req.open_batch_file();
    req.send_batch_file_data_to_server();

    print_html_before_content(all_requests);

    while( 1 ){
        // req.send_batch_file_data_to_server_once();
        std::string msg;
        msg = req.read_server_response(1024, false);
        if( msg.empty() ){
            close(req.server_fd);
            break;
        }
        nl2br(msg);
        print_html_content(req.id, msg);
    }

    print_html_after_content();
#endif

    int request_num = all_requests.size();

    for( auto& req: all_requests ){
        req.open_batch_file();
        req.connect_server(true);
    }

    // std::cerr << "send out\n";

    /* recieve msg from server and print out */
    fd_set read_fds, write_fds;
    int max_fd = -1;
    FD_ZERO(&read_fds);
    for( const auto& req: all_requests ){
        if( req.is_server_connect ){
            FD_SET(req.server_fd, &read_fds);
            if( max_fd < req.server_fd ){
                max_fd = req.server_fd;
            }
        }
    }
    max_fd += 1;

    err_log << "request_num start:" << request_num << std::endl;

    print_http_header();
    print_html_before_content(all_requests);

    while( request_num > 0 ){
        fd_set select_read_fds = read_fds;
        int s_ret = 0;
        s_ret = select(max_fd, &select_read_fds, NULL, NULL, NULL);

        err_log << "\nSELECT return: " << s_ret << std::endl;
        err_log << "request_num:" << request_num << std::endl;

        if( s_ret < 0 )
            perror_and_exit("select error");

        for( auto& req: all_requests ){
            if( FD_ISSET(req.server_fd, &select_read_fds) ){

                err_log << "fd " << req.server_fd << " can be read\n";

                std::string msg;
                msg = req.read_server_response(1024, true);

                err_log << "msg: " << msg << "\n";

                if( msg.empty() ){
                    /* this server has no response */
                    err_log << "FD_CLR: " << req.addr.ipv4_addr_str << std::endl;
                    FD_CLR(req.server_fd, &read_fds);
                    err_log << "FD_CLR finish: " << req.addr.port_hbytes << std::endl;
                    close(req.server_fd);
                    req.is_server_connect = false;
                    request_num--;
                    err_log << "request_num after clear:" << request_num << std::endl;
                    continue;
                }
                nl2br(msg);
                print_html_content(req.id, msg);

                // write to socket.
                req.send_batch_file_data_to_server_once();
            }
        }
    }

    err_log << "end of requests\n";
    print_html_after_content();
    err_log << "print_html_after_content() finish\n";

    err_log.close();
    return 0;
}
Esempio n. 16
0
int 
destroy(struct oflops_context *ctx) {
  char msg[1024];
  struct timeval now;
  FILE *out = fopen(logfile, "w");
  struct entry *np;
  long long t[3], t_sq[3], mean, std;
  int count[3], min_id[3], max_id[3];
  int ch;
  float loss;
  int xid;

  gettimeofday(&now, NULL);
  printf("destroying code\n");
  snprintf(msg, 1024, "OFPT_ERROR_DELAY:%lld", delay_false_modificaton);
  oflops_log(now, GENERIC_MSG, msg);
  snprintf(msg, 1024, "OFPT_INSERT_DELAY:%lld", delay_modificaton);
  oflops_log(now, GENERIC_MSG, msg);

  for(ch = 0; ch < ctx->n_channels-1; ch++) {
    count[ch] = 0;
    min_id[ch] =  INT_MAX;
    max_id[ch] =  INT_MIN;
    t[ch] = 0;
    t_sq[ch] = 0;    
  }

  for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next) {
    if(fprintf(out, "%lu;%lu.%06lu;%lu.%06lu;%d\n", 
	       (long unsigned int)np->id,  
	       (long unsigned int)np->snd.tv_sec, 
	       (long unsigned int)np->snd.tv_usec,
	       (long unsigned int)np->rcv.tv_sec, 
	       (long unsigned int)np->rcv.tv_usec,  np->ch) < 0)  
      perror_and_exit("fprintf fail", 1); 
    ch = np->ch - 1;
    count[ch]++; 
    min_id[ch] = (np->id < min_id[ch])?np->id:min_id[ch];
    max_id[ch] = (np->id > max_id[ch])?np->id:max_id[ch];
    t[ch] += time_diff(&np->snd, &np->rcv);
    t_sq[ch] += time_diff(&np->snd, &np->rcv)*time_diff(&np->snd, &np->rcv);
    free(np);
  }

  for(ch = 0; ch < ctx->n_channels-1; ch++) {
    if(count[ch] == 0) continue;
    mean = t[ch]/count[ch];
    std = (t_sq[ch]/count[ch]) - mean*mean;
    if(std >= 0) std = sqrt(std); else std = LONG_MAX;
    loss = (float)count[ch]/(float)(max_id[ch] - min_id[ch]);
    snprintf(msg, 1024, "statistics:port:%d:%lld:%lld:%.4f:%d", 
	     ctx->channels[ch + 1].of_port, mean, std, loss, count[ch]);
    oflops_log(now, GENERIC_MSG, msg);
  }

  t[0] = 0;
  t_sq[0] = 0;
  for (xid = 1 ; xid < trans_id; xid++) {
    t[0] +=delay[xid];
    t_sq[0] += delay[xid]*delay[xid];
  }
  std = (t_sq[0]/trans_id) - mean*mean;
  std = (std >= 0)?sqrt(std):LONG_MAX;
  snprintf(msg, 1024, "ofp_echo_statistics:%lld:%lld", 
	   t[0]/trans_id, std);
  oflops_log(now, GENERIC_MSG, msg);
  return 0;
}
Esempio n. 17
0
int socks5_connect(int client_sockfd, int *connect_sockfd_p) {
	uint8_t buffer[4];
	if (read_all(client_sockfd, buffer, 4)) return -2;
	unsigned char ver       = buffer[0];
	unsigned char cmd       = buffer[1];
	unsigned char reserved  = buffer[2];
	unsigned char addr_type = buffer[3];
	if (ver != SOCKS_VER) return -1;
	if (reserved != 0) return -1;
	if (!(addr_type == ATYP_IPV4 || addr_type == ATYP_DOMAIN || addr_type == ATYP_IPV6)) return -1;
	static address_union address;									// thread unsafe
	switch (addr_type) {
		case ATYP_IPV4: {
			if (read_all(client_sockfd, address.ipv4, 4)) return -2;
			break;
		}
		case ATYP_IPV6: {
			if (read_all(client_sockfd, address.ipv6, 16)) return -2;
			break;
		}
		case ATYP_DOMAIN: {
			if (read_all(client_sockfd, buffer, 1)) return -2;
			unsigned char domain_name_len = buffer[0];
			if (domain_name_len == 0) return -1;
			assert(sizeof(char) == 1);
			if (read_all(client_sockfd, address.domain_name, domain_name_len)) return -2;
			address.domain_name[domain_name_len] = 0;
			break;
		}
	}
	if (read_all(client_sockfd, buffer, 2)) return -2;
	unsigned int port = ntohs(*(uint16_t *)buffer);
	
	uint8_t resp_buf[10] = {
		SOCKS_VER, 0/*rep*/, 0/*rsv*/, ATYP_IPV4,
		0, 0, 0, 0/*bind.ipv4*/,
		0, 0/*bind.port*/
	};
	unsigned char rep;
	if (cmd == CMD_CONNECT) {
		rep = REP_SUCCEEDED;
		
		struct sockaddr *connect_addr;
		socklen_t connect_addr_len;
		int ret = make_sockaddr(addr_type, &address, port, &connect_addr, &connect_addr_len);
		assert(ret >= 0);
		if (ret > 0) {
			rep = ret;
		} else {
			int connect_sockfd = socket(connect_addr->sa_family, SOCK_STREAM, 0);
			if (connect_sockfd < 0) perror_and_exit("socket");
			
			if (connect(connect_sockfd, connect_addr, connect_addr_len)) {
				if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT) {
					switch (errno) {
						case ECONNREFUSED:
							rep = REP_CONNECTION_REFUSED;
							break;
						case ETIMEDOUT:
							rep = REP_HOST_UNREACHABLE;
							break;
						case ENETUNREACH:
							rep = REP_NETWORK_UNREACHABLE;
							break;
					}
					if (close(connect_sockfd)) perror_and_exit("close");
				} else perror_and_exit("connect");
			} else {
				*connect_sockfd_p = connect_sockfd;
			}
			
			free(connect_addr);
		}
	} else {
		rep = REP_COMMAND_NOT_SUPPORTED;
	}
	resp_buf[1] = rep;
	if (write_all(client_sockfd, resp_buf, sizeof(resp_buf))) {
		if (rep == REP_SUCCEEDED) {
			if (close(*connect_sockfd_p)) perror_and_exit("close");
		}
		return -2;
	}
	return (rep == REP_SUCCEEDED ? 0 : 1);
}
Esempio n. 18
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;
}