ucli_status_t vt_ucli_module__perf__(ucli_context_t* uc) { uint64_t last; uint64_t now; double seconds; uint64_t deltat = 2000000; int count = 0; int direction; uint8_t data[128] = {0}; int misscount = 0; int pid = 0; UCLI_COMMAND_INFO(uc, "perf", 2, "$summary#Receive performance test." "$args#[send|recv] vpi"); UCLI_ARGPARSE_OR_RETURN(uc, "{choice}{vpi}", &direction, "direction", 2, "send", "recv", &vtc->vpi); count = 0; last = os_time_monotonic(); while(1) { if(direction == 0) { /* send */ *(uint32_t*)(data) = pid++; vpi_send(vtc->vpi, data, sizeof(data)); count++; } else { /* recv */ if(vpi_recv__(uc, vtc) > 0) { uint32_t rpid = *(uint32_t*)(vtc->data); if(pid != rpid) { misscount += (rpid - pid); pid = rpid+1; } else { pid++; } count++; } } now = os_time_monotonic(); if((now - last) > deltat) { seconds = 1.0*(now-last)/1000000; ucli_printf(uc, "%d packets %s in %f seconds (%f pps) missed=%d\n", count, direction ? "received" : "sent", seconds, count/seconds, misscount); count=0; last = now; misscount=0; } } return UCLI_STATUS_OK; }
ucli_status_t vt_ucli_module__send__(ucli_context_t* uc) { UCLI_COMMAND_INFO(uc, "send", 2, "$summary#Send a single packet on the given VPI." "$args#<vpi_spec> <packet_data>"); UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}", &vtc->vpi, vtc->data, &vtc->size); if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) { return ucli_error(uc, "vpi_send() failed."); } return UCLI_STATUS_OK; }
ucli_status_t vt_ucli_module__sendrecv__(ucli_context_t* uc) { UCLI_COMMAND_INFO(uc, "sendrecv", 2, "$summary#Send a single packet on the given VPI and wait for a response." "$args#<vpi_spec> <packet_data>"); vtc->size = sizeof(vtc->data); UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}", &vtc->vpi, vtc->data, &vtc->size); if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) { return ucli_error(uc, "vpi_send() failed."); } if(vpi_recv__(uc, vtc) > 0) { ucli_printf(uc, "recv(%{vpi}):\n%{data}", vtc->vpi, vtc->data, vtc->size); return UCLI_STATUS_OK; } else { return UCLI_STATUS_E_ERROR; } }
ucli_status_t vt_ucli_module__spam__(ucli_context_t* uc) { aim_ratelimiter_t counter_rl; aim_ratelimiter_t send_rl; int count = 0; int last = 0; int pps = -1; UCLI_COMMAND_INFO(uc, "spam", 3, "$summary#Spam packet data on the given VPI." "$args#<vpi_spec> <packet_data> <pps>"); UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}i", &vtc->vpi, vtc->data, &vtc->size, &pps); aim_ratelimiter_init(&counter_rl, 1000000, 0, NULL); aim_ratelimiter_init(&send_rl, 1000000/pps, 0, NULL); for(;;) { uint64_t now = os_time_monotonic(); if(aim_ratelimiter_limit(&counter_rl, now) == 0) { ucli_printf(uc, "Sent %d packets - %d pps\n", count, (count - last)); last = count; } if(aim_ratelimiter_limit(&send_rl, now) == 0) { if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) { return ucli_error(uc, "vpi_send() failed."); } count++; } else { os_sleep_usecs(1); } } return UCLI_STATUS_OK; }
static void* server_thread__(void* arg) { unsigned char data[2000]; int rv; server_thread_ctrl_t* ctrl = (server_thread_ctrl_t*)(arg); int count = 0; while(ctrl->loop && count++ < 2) { /* Recv Data */ if((rv = vpi_recv(ctrl->vpi, data, sizeof(data), 1)) < 0) { VPI_MERROR("vpi_recv() returned %d", rv); return NULL; } if(rv == 0) { count--; continue; } if(rv != ctrl->expected_size) { VPI_MERROR( "vpi_recv() returned %d bytes, but expected %d bytes.", rv, ctrl->expected_size); return NULL; } if(memcmp(data, (void*)ctrl->expected_packet, ctrl->expected_size) != 0) { VPI_MERROR( "packet data mismatch."); return NULL; } /* Increment first data byte and resend */ data[0]++; if((rv = vpi_send(ctrl->vpi, data, rv)) < 0) { VPI_MERROR( "vpi_send() returned %d", rv); return NULL; } } return (void*)1; }
static int vpi_non_blocking_testcase_run__(vpi_testcase_t* testcase, vpi_t* client, vpi_t* server) { int rv; unsigned char recv_data[2000]; unsigned char send_data[200]; int send_size = sizeof(send_data); int i; vpi_t vpi_client; vpi_t vpi_server; for(i = 0; i < send_size; i++) { send_data[i] = (char)i; } if( (vpi_client = vpi_create(testcase->spec_client)) == NULL) { VPI_MERROR("vpi_create(\"%s\") failed.", testcase->spec_client); return -1; } *client = vpi_client; if(testcase->spec_server) { if( (vpi_server = (vpi_create(testcase->spec_server))) == NULL) { VPI_MERROR("vpi_create(\"%s\") failed.", testcase->spec_server); return -1; } } else { vpi_server = vpi_client; } *server = vpi_server; if(testcase->send_listener) { vpi_ioctl(vpi_client, VPI_PROTOCOL_OPCODE_REGISTER_SEND_LISTENER, (uint8_t*)testcase->send_listener, strlen(testcase->send_listener)+1); } if( (rv = vpi_send(vpi_client, send_data, send_size)) < 0) { VPI_MERROR("send() failed"); return -1; } i = 0; while(i < 10) { rv = vpi_recv(vpi_client, recv_data, sizeof(recv_data), 0); if(rv < 0) { VPI_MERROR("recv() failed %d", rv); } if(rv != 0) { /* Packet received */ if(rv != send_size) { VPI_MERROR("receive size mismatch."); return -1; } if(vpi_send(vpi_client, recv_data, rv) < 0) { VPI_MERROR("send() failed."); return -1; } i++; } rv = vpi_recv(vpi_server, recv_data, sizeof(recv_data), 0); if(rv < 0) { VPI_MERROR("recv() failed %d", rv); return -1; } if(rv != 0) { /* Packet recieved */ if(rv != send_size) { VPI_MERROR("receive size mismatch."); return -1; } if(vpi_send(vpi_server, recv_data, rv) < 0) { VPI_MERROR("send() failed."); return -1; } } } return 0; }
static int vpi_blocking_testcase_run__(vpi_testcase_t* testcase, vpi_t* client, vpi_t* server) { int rv; void* thread_rv = NULL; unsigned char recv_data[2000]; unsigned char send_data[200]; pthread_t pth; server_thread_ctrl_t sctrl; vpi_t vpi_client; int i; int size = sizeof(send_data); for(i = 0; i < size; i++) { send_data[i] = (char)i; } if( (vpi_client = vpi_create(testcase->spec_client)) == NULL) { VPI_MERROR("vpi_create(\"%s\") failed.", testcase->spec_client); return -1; } *client = vpi_client; memset(&sctrl, 0, sizeof(sctrl)); sctrl.loop = 1; if(testcase->spec_server) { if( (sctrl.vpi = vpi_create(testcase->spec_server)) == NULL) { VPI_MERROR("vpi_create(\"%s\") failed.", testcase->spec_server); return -1; } } else { sctrl.vpi = vpi_client; } *server = sctrl.vpi; sctrl.expected_size = size; sctrl.expected_packet = (char*)send_data; /* Start server thread */ if(pthread_create(&pth, NULL, server_thread__, &sctrl) < 0) { VPI_MERROR("could not create server thread: %s", strerror(errno)); return -1; } if(testcase->send_listener) { vpi_ioctl(vpi_client, VPI_PROTOCOL_OPCODE_REGISTER_SEND_LISTENER, (uint8_t*)testcase->send_listener, strlen(testcase->send_listener)+1); } send_data[0] = 0x42; if((rv=vpi_send(vpi_client, send_data, size)) < 0) { VPI_MERROR("send() returned %d: %s", rv, strerror(errno)); goto err; } do { if((rv = vpi_recv(vpi_client, recv_data, sizeof(recv_data),1)) < 0) { VPI_MERROR("recv() returned %d: %s", rv, strerror(errno)); goto err; } } while(rv == 0); if(rv != size) { VPI_MERROR("received %d bytes but expected %d\n", rv, size); goto err; } if(recv_data[0] != 0x43) { VPI_MERROR("received packet is not incremented."); goto err; } if(memcmp(recv_data+1, send_data+1, sizeof(send_data)-1) != 0) { VPI_MERROR("data mistmach."); goto err; } send_data[0] = 0x65; if((rv=vpi_send(vpi_client, send_data, sizeof(send_data))) < 0) { VPI_MERROR("send() returned %d: %s", rv, strerror(errno)); goto err; } if((rv = vpi_recv(vpi_client, recv_data, sizeof(recv_data),1)) < 0) { VPI_MERROR("recv() returned %d: %s", rv, strerror(errno)); goto err; } if(rv != sizeof(send_data)) { VPI_MERROR("received %d bytes but expected %d\n", rv, size); goto err; } if(recv_data[0] != 0x66) { VPI_MERROR("received packet is not incremented."); goto err; } if(memcmp(recv_data+1, send_data+1, sizeof(send_data)-1) != 0) { VPI_MERROR("data mistmach."); goto err; } VPI_MINFO("joining server thread."); pthread_join(pth, &thread_rv); if(thread_rv == NULL) { VPI_MINFO("server thread reported failure."); return -1; } else { VPI_MINFO("server thread reported success."); return 0; } err: sctrl.loop = 0; pthread_join(pth, &thread_rv); return -1; }