[ovs-dev] [PATCH 00/11] RFC: Improvements in upcall processing code path.

Rajahalme, Jarno (NSN - FI/Espoo) jarno.rajahalme at nsn.com
Wed Feb 13 07:29:49 UTC 2013


On Feb 13, 2013, at 0:03 , ext Ben Pfaff wrote:

> On Mon, Feb 11, 2013 at 04:46:16PM +0200, Jarno Rajahalme wrote:
>> - 'udpping' sends 10000000 UDP packets with a unique source and destination
>>  port pair to br0 in bursts of 97 packets.  Between bursts it nanosleeps
>>  for 50 nanoseconds.  This results into ~80% CPU (core) utilization.
> 
> Why are the bursts 97 packets long?
> 
> It would be great if you could supply the udpping program.  Ideally,
> you'd add it as a mode to the ovs-benchmark program in the utilities
> directory, but a quick-and-dirty C program would work too.


I'm running the test on a dual core machine, which was a challenge due to process scheduling - it was hard to get consistent results with two processes running at 100% and the rest of the system compering for CPU time. With send batching and nanosleep in between I was able to get the 'nice -n -5 udpping' to run on a fairly stable CPU load of 80%, while still saturating ovs-vswitchd's capacity to handle the upcalls in all of my test cases.

I tend to pick prime numbers for things like this to avoid synchronization with e.g. the OVS miss batch len of 50. Preferably the total packet count, batch size and the nanosleep time should be given as command line arguments, so it would be easier to tune the test to a specific situation.

It is kind of quick and dirty at this time, but I'll include it below for now so that you can comment on it or try it out. 

It takes a destination IP address as an argument (which I did not show in my email), and I run the following to get 3.3.3.3 routed to br0:

# ifconfig br0 3.3.3.2 up
# ip route add 3.3.3.3 dev br0
# arp -s -i br0 3.3.3.3 0a:00:27:00:00:55

The choices of IP addresses and the MAC address above are purely arbitrary.

udpping.c:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include <stdlib.h>
#include <string.h>

#include <time.h>

void diep(char *s)
{
  perror(s);
  exit(1);
}

#define N_SOCKS 1000
#define PORT 20000

#define DPORT 30000
#define DPORT_MAX 60000

int main(int argc, char * argv[])
{
  struct sockaddr_in si_me, dst;
  int s[N_SOCKS];
  int i;
  int error;
  int dport = DPORT;

  int number = 0;
  int total = 0;
  struct timespec sleeptime;

  if (argc < 2) {
    printf("Need IP address argument\n");
    exit(1);
  }

  for (i=0; i < N_SOCKS; i++) {
    if ((s[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
      diep("socket");

    memset((char *)&si_me, 0, sizeof(si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT+i);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(s[i], (struct sockaddr *)&si_me, sizeof(si_me)) == -1)
      diep("bind");
  }

  memset((char *)&dst, 0, sizeof(dst));
  dst.sin_family = AF_INET;
  dst.sin_port = htons(dport);
  dst.sin_addr.s_addr = inet_addr(argv[1]);

  printf("Using destination address: %x\n", dst.sin_addr.s_addr);

  sleeptime.tv_sec = 0;
  sleeptime.tv_nsec = 50;

  while (total + number < 10000000) {
    for (i=0; i < N_SOCKS && total + number < 10000000; i++) {
      dst.sin_port = htons(dport);

      error = sendto(s[i], &number, sizeof number, 0,
		     (struct sockaddr *)&dst, sizeof dst);
      if (error < 0)
	perror("sendto");

      if (++number >= 97) {
	total += number;
	number = 0;
	nanosleep(&sleeptime, NULL);
      }
    }
    if (++dport >= DPORT_MAX)
      dport = DPORT;
  }

  total += number;

  printf("\nSent %d packets\n", total);

  return 0;
}


More information about the dev mailing list