设备基于IP对每个用户配置流量控制规则,规则如下:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 192.168.0.10 flowid 1:10
上面的tc 是一个配置工具,本身是一个应用程序,tc后面的参数通过应用程序参数形式传递给tc工具
业务程序通过system方式调用tc,当并发用户量比较大时,业务进程会fork出大量tc,影响系统性能
优化的思路是用一个tc守护进程代替并发的多个tc,业务程序通过socket将配置参数发送给tc手机进程
tc守护进程是在tc进程外面套一个壳,增加一个socket 服务端,用来接收业务程序发送的tc 配置规则
源码:
int main(int argc, char **argv)
{
int socket = sock_init();
{
char cmd[256];
sprintf(cmd, "echo \"TC CONFIGSERVER RUNNING %d\" >> /var/log/tc.log", socket);
system(cmd);
}
while (socket > 0)
{
socket_monitor(socket);
}
fprintf(stderr, "TC-SERVER EXIT !\n");
return 0;
}
void socket_monitor(int sock)
{
fd_set set;
struct timeval timeout = {0};
int ret;
struct tc_rule_options_t *p_req = (struct tc_rule_options_t *)s_request_buff;
timeout.tv_sec = 0;
timeout.tv_usec = 10000; //10ms
FD_ZERO(&set);
FD_SET(sock, &set);
ret = select(sock + 1, &set, NULL, NULL, &timeout);
if (!((ret > 0) && FD_ISSET(sock, &set)))
{
return;
}
struct sockaddr_in client_socket_addr = {0};
unsigned int addr_size = sizeof(client_socket_addr);
int accept_socket = accept(sock,
(struct sockaddr *)&client_socket_addr,
&addr_size);
if (-1 == accept_socket)
{
fprintf(stderr, "tc server socket accept Failure!!!\n");
return;
}
timeout.tv_sec = 30;
timeout.tv_usec = 0;
setsockopt(accept_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
unsigned int ul_rcved_len = 0;
RCV:
ret = recv(accept_socket, s_request_buff + ul_rcved_len
,sizeof(s_request_buff) - ul_rcved_len, MSG_NOSIGNAL);
if (ret <= 0)
{
if ((-1 == ret) && (EINTR == errno))
{
goto RCV;
}
}
else
{
ul_rcved_len += ret;
if (ul_rcved_len < sizeof(struct tc_rule_options_t))
{
goto RCV;
}
//*change_point(p_req)
//char (*aaa)[32] = (char(*)[32])p_req->argv;
tc_main(p_req->argc, change_point(p_req));
close(accept_socket);
}
accept_socket = -1;
}