Exemple #1
0
static void memcpyperf(void *src, void *dst, u32 size, u32 cnt)
{
	struct timespec beforets;
	struct timespec afterts;
	long val[OUT_TRY_CNT];
	long sum = 0;
	u32 i, j;

	memset(src, 0xab, size);
	memset(dst, 0x00, size);

	for (j = 0; j < OUT_TRY_CNT; j++) {
		getnstimeofday(&beforets);
		for (i = 0; i < cnt; i++)
			memcpy(dst, src, size);
		getnstimeofday(&afterts);
		mdelay(100);
		val[j] = update_timeval(beforets, afterts)/cnt;
	}

	for (j = 0; j < OUT_TRY_CNT; j++)
		sum += val[j];

	printk(KERN_ERR "%lu\n", sum/OUT_TRY_CNT);

	if (buf_compare(src, dst, size))
		printk(KERN_ERR "copy err\n");
}
Exemple #2
0
static void cacheperf(void *vbuf, enum cachemaintenance id)
{
	struct timespec beforets;
	struct timespec afterts;
	phys_addr_t pbuf = virt_to_phys(vbuf);
	u32 pbufend, xfer_size, i;
	long timeval;

	xfer_size = START_SIZE;
	while (xfer_size <= END_SIZE) {
		pbufend = pbuf + xfer_size;
		timeval = 0;

		for (i = 0; i < try_cnt; i++) {
			memset(vbuf, i, xfer_size);
			getnstimeofday(&beforets);

			switch (id) {
			case CM_CLEAN:
				if (l1)
					dmac_map_area(vbuf, xfer_size,
							DMA_TO_DEVICE);
				if (l2)
					outer_clean_range(pbuf, pbufend);
				break;
			case CM_INV:
				if (l2)
					outer_inv_range(pbuf, pbufend);
				if (l1)
					dmac_unmap_area(vbuf, xfer_size,
							DMA_FROM_DEVICE);
				break;
			case CM_FLUSH:
				if (l1)
					dmac_flush_range(vbuf,
					(void *)((u32) vbuf + xfer_size));
				if (l2)
					outer_flush_range(pbuf, pbufend);
				break;
			case CM_FLUSHALL:
				if (l1)
					flush_cache_all();
				if (l2)
					outer_flush_all();
				break;
			}
			getnstimeofday(&afterts);
			timeval += update_timeval(beforets, afterts);
		}
		printk(KERN_INFO "%lu\n", timeval/try_cnt);
		xfer_size *= 2;
	}
}
static int cacheperf(void)
{
	u32 xfer_size;
	int i = 0;
	void *vbuf;
	phys_addr_t pbuf;
	u32 bufend;
	struct timespec beforets;
	struct timespec afterts;
	long timeval;
	vbuf = kmalloc(END_SIZE, GFP_KERNEL);
	pbuf = virt_to_phys(vbuf);

	if (mset) {
		printk(KERN_INFO "## Memset perf (ns)\n");

		xfer_size = START_SIZE;
		while (xfer_size <= END_SIZE) {
			bufend = pbuf + xfer_size;

			getnstimeofday(&beforets);
			for (i = 0; i < try_cnt; i++)
				memset(vbuf, i, xfer_size);
			getnstimeofday(&afterts);
			print_result(xfer_size, beforets, afterts);
			xfer_size *= 2;
		}
	}

	if (cops) {
		printk(KERN_INFO "## Clean perf (ns)\n");

		xfer_size = START_SIZE;
		while (xfer_size <= END_SIZE) {
			bufend = pbuf + xfer_size;
			timeval = 0;

			for (i = 0; i < try_cnt; i++) {
				memset(vbuf, i, xfer_size);
				getnstimeofday(&beforets);
				if (l1)
					dmac_map_area(vbuf, xfer_size,
							DMA_TO_DEVICE);
				if (l2)
					outer_clean_range(pbuf, bufend);
				getnstimeofday(&afterts);
				timeval += update_timeval(beforets, afterts);
				xfer_size *= 2;
			}
			printk(KERN_INFO "%lu\n", timeval);
		}
	}

	if (iops) {
		printk(KERN_INFO "## Invalidate perf (ns)\n");

		xfer_size = START_SIZE;
		while (xfer_size <= END_SIZE) {
			bufend = pbuf + xfer_size;
			timeval = 0;

			for (i = 0; i < try_cnt; i++) {
				memset(vbuf, i, xfer_size);
				getnstimeofday(&beforets);
				if (l2)
					outer_inv_range(pbuf, bufend);
				if (l1)
					dmac_unmap_area(vbuf, xfer_size,
							DMA_FROM_DEVICE);
				getnstimeofday(&afterts);
				timeval += update_timeval(beforets, afterts);
				xfer_size *= 2;
			}
			printk(KERN_INFO "%lu\n", timeval);
		}
	}

	if (fops) {
		printk(KERN_INFO "## Flush perf (ns)\n");

		xfer_size = START_SIZE;
		while (xfer_size <= END_SIZE) {
			bufend = pbuf + xfer_size;
			timeval = 0;

			for (i = 0; i < try_cnt; i++) {
				memset(vbuf, i, xfer_size);
				getnstimeofday(&beforets);
				if (l1)
					dmac_flush_range(vbuf,
					(void *)((u32) vbuf + xfer_size));
				if (l2)
					outer_flush_range(pbuf, bufend);
				getnstimeofday(&afterts);
				timeval += update_timeval(beforets, afterts);
				xfer_size *= 2;
			}
			printk(KERN_INFO "%lu\n", timeval);
		}
	}


	if (all) {
		printk(KERN_INFO "## Flush all perf (ns)\n");

		xfer_size = START_SIZE;
		while (xfer_size <= END_SIZE) {
			bufend = pbuf + xfer_size;
			timeval = 0;

			for (i = 0; i < try_cnt; i++) {
				memset(vbuf, i, xfer_size);
				getnstimeofday(&beforets);
					if (l1)
						flush_cache_all();
					if (l2)
						outer_flush_all();
				getnstimeofday(&afterts);
				timeval += update_timeval(beforets, afterts);
				xfer_size *= 2;
			}
			printk(KERN_INFO "%lu\n", timeval);
		}
	}

	kfree(vbuf);

	return 0;
}
Exemple #4
0
int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave)
{
  int fd_stdin, fd_stdout, fd_sock, fd_max;
  int read_ret, write_ret;
  #ifdef  __MVS__             /* zosunix01 26.07.2011 */
  unsigned char buf[32768];
  #else
  unsigned char buf[1024]; 
  #endif 
  bool inloop = TRUE;
  fd_set ins, outs;
  struct timeval delayer;
  assert(nc_main && nc_slave);

  debug_v(("core_readwrite(nc_main=%p, nc_slave=%p)", (void *)nc_main,
	  (void *)nc_slave));

  /* set the actual input and output fds and find out the max fd + 1 */
  fd_sock = nc_main->fd;
  assert(fd_sock >= 0);

  /* if the domain is unspecified, it means that this is the standard I/O */
  if (nc_slave->domain == PF_UNSPEC) {
    fd_stdin = STDIN_FILENO;
    fd_stdout = STDOUT_FILENO;
  }
  else {
    fd_stdin = fd_stdout = nc_slave->fd;
    assert(fd_stdin >= 0);
  }
  fd_max = 1 + (fd_stdin > fd_sock ? fd_stdin : fd_sock);
  delayer.tv_sec = 0;
  delayer.tv_usec = 0;

  /* use the internal signal handler */
  signal_handler = FALSE;

  while (inloop) {
    bool call_select = TRUE;
    struct sockaddr_in recv_addr;	/* only used by UDP proto */
    unsigned int recv_len = sizeof(recv_addr);

    /* if we received an interrupt signal break this function */
    if (got_sigint) {
      got_sigint = FALSE;
      break;
    }
    /* if we received a terminating signal we must terminate */
    if (got_sigterm)
      break;

    /* reset the ins and outs events watch because some changes could happen */
    FD_ZERO(&ins);
    FD_ZERO(&outs);

    /* if the receiving queue is not empty it means that something bad is
       happening (for example the target sending queue is delaying the output
       and so requires some more time to free up. */
    if (nc_main->recvq.len == 0) {
      debug_v(("watching main sock for incoming data (recvq is empty)"));
      FD_SET(fd_sock, &ins);
    }
    else
      call_select = FALSE;

    /* same thing for the other socket */
    if (nc_slave->recvq.len == 0) { /* FIXME: call_select = false but could call it
	anyway and one of them could be set.. so what happens? */
      debug_v(("watching slave sock for incoming data (recvq is empty)"));
      if (use_stdin || (netcat_mode == NETCAT_TUNNEL))
        FD_SET(fd_stdin, &ins);
    }
    else
      call_select = FALSE;

    /* now the send queue. There are two cases in which the main sendq is not
       empty.  The first one is when we have a delayed output (-i), in which
       case the delayer is not null, and the socket is writable.  The second
       case is when the socket buffer is full, so the socket is not writable
       and the delayer is either null or set, depending on the opt_interval
       variable. */
    if (nc_main->sendq.len > 0) {
      if ((delayer.tv_sec == 0) && (delayer.tv_usec == 0)) {
	debug_v(("watching main sock for outgoing availability (there is pending data)"));
	FD_SET(fd_sock, &outs);
	call_select = TRUE;
      }
    }

    if (call_select || delayer.tv_sec || delayer.tv_usec) {
      int ret;
#ifndef USE_LINUX_SELECT
      struct timeval dd_saved;

      dd_saved.tv_sec = delayer.tv_sec;
      dd_saved.tv_usec = delayer.tv_usec;
      update_timeval(NULL);
#endif

      debug(("[select] entering with timeout=%d:%d ...", delayer.tv_sec, delayer.tv_usec));
      ret = select(fd_max, &ins, &outs, NULL,
		   (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL));

#ifndef USE_LINUX_SELECT
      delayer.tv_sec = dd_saved.tv_sec;
      delayer.tv_usec = dd_saved.tv_usec;
      update_timeval(&delayer);
#endif

      if (ret < 0) {			/* something went wrong (maybe a legal signal) */
	if (errno == EINTR)
	  goto handle_signal;
	perror("select(core_readwrite)");
	exit(EXIT_FAILURE);
      }
      else if (ret == 0) {		/* timeout expired */
	delayer.tv_sec = 0;
	delayer.tv_usec = 0;
      }

      call_select = TRUE;
      debug(("ret=%d\n", ret));
    }

    /* reading from stdin the incoming data.  The data is currently in the
       kernel's receiving queue, and in this session we move that data to our
       own receiving queue, located in the socket object.  We can be sure that
       this queue is empty now because otherwise this fd wouldn't have been
       watched. */
    if (call_select && FD_ISSET(fd_stdin, &ins)) {
      read_ret = read(fd_stdin, buf, sizeof(buf));
      debug_dv(("read(stdin) = %d", read_ret));

      if (read_ret < 0) {
	perror("read(stdin)");
	exit(EXIT_FAILURE);
      }
      else if (read_ret == 0) {
	/* when we receive EOF and this is a tunnel say goodbye, otherwise
	   it means that stdin has finished its input. */
	if ((netcat_mode == NETCAT_TUNNEL) || opt_eofclose) {
	  debug_v(("EOF Received from stdin! (exiting from loop..)"));
	  inloop = FALSE;
	}
	else {
	  debug_v(("EOF Received from stdin! (removing from lookups..)"));
	  use_stdin = FALSE;
	}
      }
      else {
	/* we can overwrite safely since if the receive queue is busy this fd
	   is not watched at all. */
        nc_slave->recvq.len = read_ret;
        nc_slave->recvq.head = NULL;
        nc_slave->recvq.pos = buf;
      }
    }

    /* for optimization reasons we have a common buffer for both receiving
       queues, because of this, handle the data now so the buffer is available
       for the other socket events. */
    if (nc_slave->recvq.len > 0) {
      nc_buffer_t *my_recvq = &nc_slave->recvq;
      nc_buffer_t *rem_sendq = &nc_main->sendq;
      debug_v(("there are %d data bytes in slave->recvq", my_recvq->len));

      /* if the remote send queue is empty, move there the entire data block */
      if (rem_sendq->len == 0) {
	debug_v(("  moved %d data bytes from slave->recvq to main->sendq", my_recvq->len));
	memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
	memset(my_recvq, 0, sizeof(*my_recvq));
      }
      else if (!my_recvq->head) {
	/* move the data block in a dedicated allocated space */
	debug_v(("  reallocating %d data bytes in slave->recvq", my_recvq->len));
	my_recvq->head = malloc(my_recvq->len);
	memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
	my_recvq->pos = my_recvq->head;
      }
    }

    /* now handle the nc_slave sendq because of the same reason as above. There
       could be a common buffer that moves around the queues, so if this is the case
       handle it so that it can be reused. If we must delay it some more, copy it
       in a dynamically allocated space. */
    if (nc_main->sendq.len > 0) {
      unsigned char *data = nc_main->sendq.pos;
      int data_len = nc_main->sendq.len;
      nc_buffer_t *my_sendq = &nc_main->sendq;

      debug_v(("there are %d data bytes in main->sendq", my_sendq->len));

      /* we have a delayed output, but at this point we might have the
         send queue pointing to a stack buffer.  In this case, allocate a
         new buffer and copy the data there for the buffered output. */
      if (opt_interval) {
	int i = 0;

	if (delayer.tv_sec || delayer.tv_usec)
	  goto skip_sect;		/* the delay is not yet over! */

	/* find the newline character.  We are going to output the first line
	   immediately while we allocate and safe the rest of the data for a
	   later output. */
	while (i < data_len)
	  if (data[i++] == '\n')
	    break;

	data_len = i;
	delayer.tv_sec = opt_interval;
      }

      write_ret = write(fd_sock, data, data_len);
      if (write_ret < 0) {
        #ifdef  __MVS__          /* zosunix01 26.07.2011                   */ 
                                 /* z/OS Unix is Unix V and here the errno */
                                 /* EWOULBBLOCK appears, if the socket is  */
                                 /* blocked.                               */
	if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
        #else
        if (errno == EAGAIN)
        #endif
	  write_ret = 0;	/* write would block, append it to select */
	else {
	  perror("write(net)");
	  exit(EXIT_FAILURE);
	}
      }

      /* FIXME: fix the below unhandled exception, and find a way to delay the
       * tries to call write(2) in case of EAGAIN, i think 100ms would be fine
       * for most systems. A too high value would not use all the bandwidth on
       * bigger installations, while a too small value would eat cpu with
       * kernel overhead. */

      bytes_sent += write_ret;		/* update statistics */
      debug_dv(("write(net) = %d (buf=%p)", write_ret, (void *)data));

      if (write_ret < data_len) {
	debug_v(("Damn! I wanted to send to sock %d bytes but it only sent %d",
		data_len, write_ret));
	data_len = write_ret;
      }

      /* if the option is set, hexdump the sent data */
      if (opt_hexdump) {
#ifndef USE_OLD_HEXDUMP
	fprintf(output_fp, "Sent %u bytes to the socket\n", write_ret);
#endif
	netcat_fhexdump(output_fp, '>', data, data_len);
      }

      /* update the queue */
      my_sendq->len -= data_len;
      my_sendq->pos += data_len;

 skip_sect:
      debug_v(("there are %d data bytes left in the queue", my_sendq->len));
      if (my_sendq->len == 0) {
	free(my_sendq->head);
	memset(my_sendq, 0, sizeof(*my_sendq));
      }
      else if (!my_sendq->head) {
	my_sendq->head = malloc(my_sendq->len);
	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
	my_sendq->pos = my_sendq->head;
      }

    }				/* end of reading from stdin section */

    /* reading from the socket (net). */
    if (call_select && FD_ISSET(fd_sock, &ins)) {
      if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) {
	memset(&recv_addr, 0, sizeof(recv_addr));
	/* this allows us to fetch packets from different addresses */
	read_ret = recvfrom(fd_sock, buf, sizeof(buf), 0,
			    (struct sockaddr *)&recv_addr, &recv_len);
	/* when recvfrom() call fails, recv_addr remains untouched */
	debug_dv(("recvfrom(net) = %d (address=%s:%d)", read_ret,
		netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port)));
      }
      else {
	/* common file read fallback */
	read_ret = read(fd_sock, buf, sizeof(buf));
	debug_dv(("read(net) = %d", read_ret));
      }

      if (read_ret < 0) {
	perror("read(net)");
	exit(EXIT_FAILURE);
      }
      else if (read_ret == 0) {
	debug_v(("EOF Received from the net"));
	inloop = FALSE;
      }
      else {
	nc_main->recvq.len = read_ret;
	nc_main->recvq.head = NULL;
	nc_main->recvq.pos = buf;
      }
    }

    /* handle net receiving queue */
    if (nc_main->recvq.len > 0) {
      nc_buffer_t *my_recvq = &nc_main->recvq;
      nc_buffer_t *rem_sendq = &nc_slave->sendq;

      /* check for telnet codes (if enabled).  Note that the buffered output
         interval does NOT apply to telnet code answers */
      if (opt_telnet)
	netcat_telnet_parse(nc_main);

      /* the telnet parsing could have returned 0 chars! */
      if (my_recvq->len > 0) {
	/* if the remote send queue is empty, move there the entire data block */
	if (rem_sendq->len == 0) {
	  memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
	  memset(my_recvq, 0, sizeof(*my_recvq));
	}
	else if (!my_recvq->head) {
	  /* move the data block in a dedicated allocated space */
	  my_recvq->head = malloc(my_recvq->len);
	  memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
	  my_recvq->pos = my_recvq->head;
	}
      }
    }

    if (nc_slave->sendq.len > 0) {
      unsigned char *data = nc_slave->sendq.pos;
      int data_len = nc_slave->sendq.len;
      nc_buffer_t *my_sendq = &nc_slave->sendq;

      write_ret = write(fd_stdout, data, data_len);
      bytes_recv += write_ret;		/* update statistics */
      debug_dv(("write(stdout) = %d", write_ret));

      if (write_ret < 0) {
	perror("write(stdout)");
	exit(EXIT_FAILURE);
      }

      /* FIXME: unhandled exception */
      assert((write_ret > 0) && (write_ret <= data_len));

      if (write_ret < data_len) {
	debug_v(("Damn! I wanted to send to stdout %d bytes but it only sent %d",
		data_len, write_ret));
	data_len = write_ret;
      }

      /* if option is set, hexdump the received data */
      if (opt_hexdump) {
#ifndef USE_OLD_HEXDUMP
	if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero)
	  fprintf(output_fp, "Received %d bytes from %s:%d\n", write_ret,
		  netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port));
	else
	  fprintf(output_fp, "Received %d bytes from the socket\n", write_ret);
#endif
	netcat_fhexdump(output_fp, '<', data, write_ret);
      }

      /* update the queue */
      my_sendq->len -= data_len;
      my_sendq->pos += data_len;

      debug_v(("there are %d data bytes left in the queue", my_sendq->len));
      if (my_sendq->len == 0) {
	free(my_sendq->head);
	memset(my_sendq, 0, sizeof(*my_sendq));
      }
      else if (!my_sendq->head) {
	my_sendq->head = malloc(my_sendq->len);
	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
	my_sendq->pos = my_sendq->head;
      }
      
    }				/* end of reading from the socket section */

 handle_signal:			/* FIXME: i'm not sure this is the right place */
    if (got_sigusr1) {
      debug_v(("LOCAL printstats!"));
      netcat_printstats(TRUE);
      got_sigusr1 = FALSE;
    }
    continue;
  }				/* end of while (inloop) */

  /* we've got an EOF from the net, close the sockets */
  shutdown(fd_sock, SHUT_RDWR);  
  close(fd_sock);
  nc_main->fd = -1;

  /* close the slave socket only if it wasn't a simulation */
  if (nc_slave->domain != PF_UNSPEC) {
    shutdown(fd_stdin, SHUT_RDWR);
    close(fd_stdin);
    nc_slave->fd = -1;
  }

  /* restore the extarnal signal handler */
  signal_handler = TRUE;

  return 0;
}				/* end of core_readwrite() */