#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#define BWCALC_SML 256
#define MAX_BW (1 << 18)
#define PAGE_SIZE 1024
#define ALIGN_DOWN(x, n) (((x)) & ~((n) - 1ULL))
typedef unsigned long long longlong;
typedef struct _bw_ctrl_info{
longlong x0;
unsigned long y0;
unsigned long maxbw;
unsigned long rate;
}bw_ctrl_info, *pbw_ctrl_info;
static bw_ctrl_info bi;
longlong gettickcount()
{
struct timeb tp;
ftime(&tp);
return ((longlong)tp.time) * 1000 + tp.millitm;
}
unsigned long bw_ctrl_getcurrate(bw_ctrl_info *pbi)
{
longlong tick = gettickcount() - pbi->x0;
if(tick > (BWCALC_SML << 1))
return 0;
return pbi->rate;
}
int bwctl_filter(bw_ctrl_info *pbi, unsigned short len)
{
longlong ll;
longlong tick = gettickcount();
if((pbi->y0 + (len << 3)) > (((pbi->maxbw) / 1000) * (tick - pbi->x0)))
return 0;
pbi->y0 += (len << 3);
ll = (longlong)pbi->y0;
pbi->rate = (unsigned long)(ll * 1000 / (tick - pbi->x0));
if((tick - pbi->x0) > BWCALC_SML){
pbi->y0 = pbi->y0 * (BWCALC_SML >> 1) / (tick - pbi->x0);
pbi->x0 = tick - (BWCALC_SML >> 1);
}
return 1;
}
int main(int argc, char *argv[])
{
int i;
char *arg;
char *ptr;
int num;
int ret;
void *viraddr;
size_t map_length;
unsigned int val;
unsigned long long addr;
unsigned long long map_addr;
unsigned long long t1;
unsigned long long max_bw;
unsigned long long bar2Addr;
unsigned int unit_size = 0;
unsigned long long unit_value = 0;
int mem_fd = -1;
unsigned int count = 0;
t1 = gettickcount();
bi.maxbw = MAX_BW;
if ((argc < 2) || (argc > 3))
{
printf("invalid para\n");
return -1;
}
if ((argv[1][0] == '0') && (argv[1][1] == 'x')) {
bar2Addr = strtoull(&argv[1][2], NULL, 16);
} else {
bar2Addr = strtoull(&argv[1][0], NULL, 16);
}
if (argc == 3) {
if ((argv[2][0] == '0') && (argv[2][1] == 'x')) {
max_bw = strtoull(&argv[2][2], NULL, 16);
} else {
max_bw = strtoull(&argv[2][0], NULL, 16);
}
bi.maxbw = max_bw & ~(1024);
}
mem_fd = open("/dev/mem_map", O_RDWR);
if (mem_fd < 0) {
perror("open /dev/mem failed");
return -3;
}
map_addr = ALIGN_DOWN(bar2Addr, PAGE_SIZE);
map_length = bar2Addr - map_addr + 4;
viraddr = mmap(NULL, map_length, PROT_WRITE, MAP_SHARED, mem_fd, map_addr);
if (viraddr == MAP_FAILED) {
perror("mmap failed");
printf("mmap addr:0x%016llx size:0x%08lx failed\n", map_addr, map_length);
close(mem_fd);
return -4;
}
viraddr = (char*)viraddr + bar2Addr - map_addr;
while(1){
srand((unsigned)time(NULL));
num = rand();
val = num;
*(unsigned int *)viraddr = (unsigned int)val;
ret = bwctl_filter(&bi, 16+4);
if(ret <= 0){
usleep(10);
continue;
}
count++;
if((gettickcount() - t1) > 1000) {
printf("\nnum = %x, rate = %8d kbps, count = %d", num, bw_ctrl_getcurrate(&bi) >> 10, count);
t1 = gettickcount();
count = 0;
}
}
///< clean
munmap(viraddr, map_length);
close(mem_fd);
return 0;
}