913 lines
36 KiB
C
913 lines
36 KiB
C
//
|
|
// Created by xajhuang on 2023/4/12.
|
|
//
|
|
#include <zlog.h>
|
|
#include <sys/time.h>
|
|
#include "main.h"
|
|
#include "misc.h"
|
|
#include "task_manager.h"
|
|
#include "user_errno.h"
|
|
#include "zlog_module.h"
|
|
#include "dhcp_network.h"
|
|
#include "dhcp_options.h"
|
|
#include "ipaddr.h"
|
|
#include "zvector/zvector.h"
|
|
|
|
#define DHCP_STEP_TIMEOUT (30)
|
|
#define DHCP_PKG_RETRY (3)
|
|
|
|
#define MAIN_WND_WIDTH (1024)
|
|
#define MAIN_WND_HEIGHT (768)
|
|
|
|
#define ZLOG_CFG_PATH "./config/zlog.conf"
|
|
|
|
static GtkBuilder *g_mainBuilder = NULL;
|
|
static PDHCP_INFO g_pDhcpInfo = NULL;
|
|
static GThread *g_pEvLoopThread = NULL;
|
|
static int g_runTask = FALSE;
|
|
static U32 g_endTask = 0;
|
|
static c_vector g_pFinishTask = NULL;
|
|
static c_vector g_pErrTask = NULL;
|
|
static struct timeval g_StartTm;
|
|
|
|
const char *dhcp_step_to_string(DHCP_STEP step) {
|
|
const char *stepName[] = {"STEP_BEGIN", "STEP_DISCOVER", "STEP_OFFER", "STEP_REQUEST", "STEP_ACK", "STEP_END"};
|
|
|
|
if (step > 0 && step < ARRAY_SIZE(stepName)) {
|
|
return stepName[step];
|
|
} else {
|
|
return "Unknown Step";
|
|
}
|
|
}
|
|
|
|
GtkBuilder *get_main_builder() {
|
|
return g_mainBuilder;
|
|
}
|
|
|
|
U32 rand_number() {
|
|
GRand *pRand = g_rand_new_with_seed(time(NULL));
|
|
|
|
return g_rand_int(pRand);
|
|
}
|
|
|
|
PDHCP_INFO get_dhcp_info_by_id(U32 xid) {
|
|
PDHCP_INFO pInfo;
|
|
U32 index = xid & 0x00FFFFFF;
|
|
|
|
HASH_FIND_INT(g_pDhcpInfo, &index, pInfo);
|
|
return pInfo;
|
|
}
|
|
|
|
static void load_css(void) {
|
|
GtkCssProvider *provider;
|
|
GdkDisplay *display;
|
|
GdkScreen *screen;
|
|
GFile *css_fp = g_file_new_for_path("./res/style.css");
|
|
GError *error = 0;
|
|
|
|
provider = gtk_css_provider_new();
|
|
display = gdk_display_get_default();
|
|
screen = gdk_display_get_default_screen(display);
|
|
|
|
gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
|
|
gtk_css_provider_load_from_file(provider, css_fp, &error);
|
|
}
|
|
|
|
static double calc_total_progress(PDHCP_INFO pInfo) {
|
|
double pre_cnt = 0.0;
|
|
|
|
pre_cnt += pInfo->step * 20;
|
|
pre_cnt += pInfo->status * 5;
|
|
|
|
return MIN(pre_cnt, 100.0);
|
|
}
|
|
|
|
static gboolean calc_step_progress(PDHCP_INFO pInfo, DHCP_STEP step) {
|
|
if (pInfo->step >= step) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void get_task_result(PDHCP_INFO pInfo, char *pInBuf, int maxBuf) {
|
|
if (pInfo->status == STA_ERROR) {
|
|
snprintf(pInBuf, maxBuf, "Error at %s", dhcp_step_to_string(pInfo->step));
|
|
} else if (pInfo->step == STEP_END) {
|
|
int ret;
|
|
DHCP_OPT opt;
|
|
const char *pIp = NULL, *pNetmask = NULL, *pDns1 = NULL, *pDns2 = NULL;
|
|
U32 optSize = 0;
|
|
PDHCP_PROTO pDhcp = get_dhcp_date(pInfo->pAckBuf.p, &optSize, pInfo->pAckBuf.buf_size);
|
|
|
|
pIp = u32_to_str_ip_safe(pDhcp->yiaddr);
|
|
ret = dhcp_get_option(OPT_NETMASK, pDhcp->options, optSize, &opt);
|
|
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
|
|
pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue));
|
|
}
|
|
|
|
ret = dhcp_get_option(OPT_DNS, pDhcp->options, optSize, &opt);
|
|
if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) {
|
|
U32 *pVal = (U32 *)opt.pValue;
|
|
pDns1 = u32_to_str_ip_safe(*pVal);
|
|
|
|
if (opt.len > sizeof(U32)) {
|
|
pVal++;
|
|
pDns2 = u32_to_str_ip_safe(*pVal);
|
|
}
|
|
}
|
|
|
|
snprintf(pInBuf, maxBuf, "IP: %s/%u, DNS: [%s, %s]", pIp, ipv4_mask_to_cidr(pNetmask), pDns1, pDns2);
|
|
|
|
if (pIp) {
|
|
free((void *)pIp);
|
|
}
|
|
|
|
if (pDns1) {
|
|
free((void *)pDns1);
|
|
}
|
|
|
|
if (pDns2) {
|
|
free((void *)pDns2);
|
|
}
|
|
|
|
if (pNetmask) {
|
|
free((void *)pNetmask);
|
|
}
|
|
} else {
|
|
pInBuf[0] = 0;
|
|
}
|
|
}
|
|
|
|
void view_popup_menu_onStatistics(GtkWidget *UNUSED(menuitem), gpointer userdata) {
|
|
//PDHCP_INFO pInfo = (PDHCP_INFO)userdata;
|
|
//hex_wnd_show(pInfo);
|
|
}
|
|
|
|
void view_popup_menu_onBinaryPkg(GtkWidget *UNUSED(menuitem), gpointer userdata) {
|
|
PDHCP_INFO pInfo = (PDHCP_INFO)userdata;
|
|
//GtkWidget *deatilWnd = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "wndDetails"));
|
|
//
|
|
//g_print("Do something of %s\n", pInfo->treeId);
|
|
//gtk_notebook_set_current_page(GTK_NOTEBOOK(tab), 0);
|
|
//gtk_widget_show(deatilWnd);
|
|
details_wnd_show(pInfo);
|
|
}
|
|
|
|
void view_popup_menu(GtkWidget *UNUSED(treeview), GdkEventButton *event, gpointer userdata) {
|
|
GtkWidget *menu, *menuitem;
|
|
|
|
menu = gtk_menu_new();
|
|
|
|
menuitem = gtk_menu_item_new_with_label("数据包详情");
|
|
g_signal_connect(menuitem, "activate", (GCallback)view_popup_menu_onBinaryPkg, userdata);
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
|
|
|
menuitem = gtk_menu_item_new_with_label("统计信息");
|
|
g_signal_connect(menuitem, "activate", (GCallback)view_popup_menu_onStatistics, userdata);
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
|
|
|
gtk_widget_show_all(menu);
|
|
gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent *)event);
|
|
}
|
|
|
|
gboolean view_onButtonPressed(GtkWidget *treeview, GdkEventButton *event, gpointer UNUSED(userdata)) {
|
|
gboolean showMenu = FALSE;
|
|
|
|
PDHCP_INFO p = NULL;
|
|
GtkTreeIter iter;
|
|
GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo"));
|
|
/* single click with the right mouse button? */
|
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
|
/* optional: select row if no row is selected or only
|
|
* one other row is selected (will only do something
|
|
* if you set a tree selection mode as described later
|
|
* in the tutorial) */
|
|
GtkTreeSelection *selection;
|
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
|
|
/* Note: gtk_tree_selection_count_selected_rows() does not
|
|
* exist in gtk+-2.0, only in gtk+ >= v2.2 ! */
|
|
if (gtk_tree_selection_count_selected_rows(selection) <= 1) {
|
|
GtkTreePath *path;
|
|
|
|
/* Get tree path for row that was clicked */
|
|
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, NULL,
|
|
NULL, NULL)) {
|
|
|
|
gtk_tree_selection_unselect_all(selection);
|
|
gtk_tree_selection_select_path(selection, path);
|
|
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) {
|
|
gchar *index;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, COL_INDEX, &index, -1);
|
|
if (index[0] != 'V') {
|
|
U32 id = strtoul(index, NULL, 10);
|
|
HASH_FIND_INT(g_pDhcpInfo, &id, p);
|
|
if (p) {
|
|
showMenu = TRUE;
|
|
}
|
|
}
|
|
g_free(index);
|
|
}
|
|
gtk_tree_path_free(path);
|
|
}
|
|
}
|
|
|
|
if (showMenu) {
|
|
view_popup_menu(treeview, event, p);
|
|
}
|
|
return TRUE; /* we handled this */
|
|
}
|
|
|
|
return FALSE; /* we did not handle this */
|
|
}
|
|
|
|
gboolean view_onPopupMenu(GtkWidget *treeview, gpointer userdata) {
|
|
view_popup_menu(treeview, NULL, userdata);
|
|
return TRUE; /* we handled this */
|
|
}
|
|
|
|
static void tree_view_data_store_create() {
|
|
int i, j;
|
|
PDHCP_INFO pInfo, pTemp;
|
|
GtkTreeIter iter, iter_child;
|
|
GtkWidget *view = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "treeResult"));
|
|
GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo"));
|
|
GtkWidget *vniStart = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVni"));
|
|
GtkWidget *numRequest = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbReqNum"));
|
|
int nRequest = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numRequest));
|
|
int nVni = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vniStart));
|
|
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL);
|
|
gtk_tree_store_clear(store);
|
|
|
|
for (i = 0; i < nRequest; i++) {
|
|
int isCreateRoot = FALSE;
|
|
j = 0;
|
|
HASH_ITER(hh, g_pDhcpInfo, pInfo, pTemp) {
|
|
if (pInfo->vni == (nVni + i)) {
|
|
char idx[64] = {0};
|
|
char mac[24] = {0};
|
|
|
|
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", pInfo->mac[0], pInfo->mac[1], pInfo->mac[2],
|
|
pInfo->mac[3], pInfo->mac[4], pInfo->mac[5]);
|
|
|
|
if (!isCreateRoot) {
|
|
sprintf(idx, "VNI %d", nVni + i);
|
|
// 创建根节点
|
|
gtk_tree_store_append(store, &iter, NULL);
|
|
// clang-format off
|
|
gtk_tree_store_set(store,
|
|
&iter,
|
|
COL_INDEX, idx,
|
|
COL_RESULT, "",
|
|
COL_STATUS, calc_total_progress(pInfo),
|
|
COL_ATTR_EDITABLE, FALSE,
|
|
COL_ATTR_VISIABLE, FALSE,
|
|
-1);
|
|
// clang-format on
|
|
isCreateRoot = TRUE;
|
|
}
|
|
|
|
gtk_tree_store_append(store, &iter_child, &iter);
|
|
|
|
// clang-format off
|
|
// 创建子节点
|
|
memset(idx, 0, 64);
|
|
sprintf(idx, "%u", pInfo->index);
|
|
gtk_tree_store_set(store,
|
|
&iter_child,
|
|
COL_INDEX, idx,
|
|
COL_MAC, mac,
|
|
COL_HOSTNAME, pInfo->hostname,
|
|
COL_DISCOVER, calc_step_progress(pInfo, STEP_DISCOVER),
|
|
COL_OFFER, calc_step_progress(pInfo, STEP_OFFER),
|
|
COL_REQUEST, calc_step_progress(pInfo, STEP_REQUEST),
|
|
COL_ACK, calc_step_progress(pInfo, STEP_ACK),
|
|
COL_RESULT, "",
|
|
COL_STATUS, calc_total_progress(pInfo),
|
|
COL_ATTR_EDITABLE, FALSE,
|
|
COL_ATTR_VISIABLE, TRUE,
|
|
-1);
|
|
// clang-format on
|
|
memset(pInfo->treeId, 0, 32);
|
|
sprintf(pInfo->treeId, "%d:%d", i, j++);
|
|
}
|
|
}
|
|
}
|
|
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
|
|
|
|
g_signal_connect(view, "button-press-event", (GCallback)view_onButtonPressed, NULL);
|
|
g_signal_connect(view, "popup-menu", (GCallback)view_onPopupMenu, NULL);
|
|
|
|
#if 0
|
|
for (i = 0; i < 1000; i++) {
|
|
char buf[24] = {0};
|
|
char bufHost[32] = {0};
|
|
char bufVni[16] = {0};
|
|
|
|
sprintf(bufVni, "%d", i);
|
|
sprintf(bufHost, "hostname%d", i);
|
|
sprintf(buf, "06:01:02:%02X:%02X:%02X", (i & 0xFF0000) >> 16, (i & 0xFF00) >> 8, (i & 0xFF));
|
|
|
|
gtk_tree_store_append(store, &iter, NULL);
|
|
// clang-format off
|
|
gtk_tree_store_set(store, &iter,
|
|
COL_INDEX, bufVni,
|
|
COL_MAC, buf,
|
|
COL_HOSTNAME, bufHost,
|
|
COL_STATUS, 20.0,
|
|
-1);
|
|
gtk_tree_store_append(store, &iter_child, &iter);
|
|
gtk_tree_store_set(store, &iter_child,
|
|
COL_INDEX, "",
|
|
COL_STEP, "Discover",
|
|
COL_RESULT, "",
|
|
COL_STATUS, 10.0,
|
|
-1);
|
|
gtk_tree_store_append(store, &iter_child, &iter);
|
|
gtk_tree_store_set(store, &iter_child,
|
|
COL_INDEX, "",
|
|
COL_STEP, "Offer",
|
|
COL_RESULT, "",
|
|
COL_STATUS, 10.0,
|
|
-1);
|
|
|
|
gtk_tree_store_append(store, &iter_child, &iter);
|
|
gtk_tree_store_set(store, &iter_child,
|
|
COL_INDEX, "",
|
|
COL_STEP, "Request",
|
|
COL_RESULT, "",
|
|
COL_STATUS, 10.0,
|
|
-1);
|
|
gtk_tree_store_append(store, &iter_child, &iter);
|
|
gtk_tree_store_set(store, &iter_child,
|
|
COL_INDEX, "",
|
|
COL_STEP, "ACK",
|
|
COL_RESULT, "",
|
|
COL_STATUS, 10.0,
|
|
-1);
|
|
// clang-format on
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static gboolean upgrade_status_bar_msg(gpointer UNUSED(pInfo)) {
|
|
int tolTask = HASH_COUNT(g_pDhcpInfo);
|
|
char buf[1024] = {0};
|
|
static S32 tmdiff = 0;
|
|
GtkWidget *statusBar = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "labMsg"));
|
|
GtkWidget *prgBar = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "prgTotal"));
|
|
double percnt = vect_size(g_pErrTask) + vect_size(g_pFinishTask);
|
|
|
|
if (g_runTask) {
|
|
struct timeval tvNow;
|
|
gettimeofday(&tvNow, NULL);
|
|
tmdiff = MAX(0, (tvNow.tv_sec * 1000000 + tvNow.tv_usec) - (g_StartTm.tv_sec * 1000000 + g_StartTm.tv_usec));
|
|
}
|
|
|
|
sprintf(buf, "Statistics: total %d | successed %d | error %d | total time %d.%03d(seconds)", tolTask,
|
|
MIN(vect_size(g_pFinishTask), tolTask), vect_size(g_pErrTask), tmdiff / 1000000, (tmdiff % 1000000) / 1000);
|
|
|
|
gtk_label_set_text(GTK_LABEL(statusBar), buf);
|
|
|
|
if (tolTask > 0) {
|
|
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prgBar), percnt / tolTask);
|
|
} else {
|
|
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prgBar), 0.0);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean upgade_task(gpointer pInfo) {
|
|
return FALSE;
|
|
}
|
|
|
|
static void tree_view_data_store_upgade(gpointer pInfo) {
|
|
GtkTreeIter iter;
|
|
GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo"));
|
|
GtkTreeModel *model;
|
|
PDHCP_INFO p = (PDHCP_INFO)pInfo;
|
|
|
|
if (!pInfo || !store || !g_runTask) {
|
|
return;
|
|
}
|
|
|
|
model = GTK_TREE_MODEL(store);
|
|
|
|
if (model && gtk_tree_model_get_iter_from_string(model, &iter, p->treeId)) {
|
|
char info[256] = {0};
|
|
get_task_result(p, info, 256);
|
|
|
|
// clang-format off
|
|
gtk_tree_store_set(store,
|
|
&iter,
|
|
COL_DISCOVER, calc_step_progress(pInfo, STEP_DISCOVER),
|
|
COL_OFFER, calc_step_progress(pInfo, STEP_OFFER),
|
|
COL_REQUEST, calc_step_progress(pInfo, STEP_REQUEST),
|
|
COL_ACK, calc_step_progress(pInfo, STEP_ACK),
|
|
COL_RESULT, info,
|
|
COL_STATUS, calc_total_progress(pInfo),
|
|
COL_ATTR_EDITABLE, FALSE,
|
|
COL_ATTR_VISIABLE, TRUE,
|
|
-1);
|
|
// clang-format on
|
|
|
|
if (strlen(info) > 0 && p->close == FALSE) {
|
|
p->close = TRUE;
|
|
g_endTask++;
|
|
}
|
|
}
|
|
|
|
if (g_endTask == HASH_COUNT(g_pDhcpInfo)) {
|
|
GtkWidget *startButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStart"));
|
|
GtkWidget *stoptButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStop"));
|
|
GtkWidget *nicSelect = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "cbNicName"));
|
|
GtkWidget *tbExpand = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbExpand"));
|
|
|
|
g_runTask = FALSE;
|
|
gtk_widget_set_sensitive(GTK_WIDGET(stoptButton), FALSE);
|
|
gtk_widget_set_sensitive(startButton, TRUE);
|
|
gtk_widget_set_sensitive(nicSelect, TRUE);
|
|
g_object_set(G_OBJECT(tbExpand), "stock_id", "gtk-indent", NULL);
|
|
upgrade_status_bar_msg(NULL);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 0, "Finish test, successed %d, error %d\n", vect_size(g_pFinishTask),
|
|
vect_size(g_pErrTask));
|
|
}
|
|
}
|
|
|
|
static void mainWnd_on_destroy(GObject *UNUSED(object), gpointer UNUSED(user_data)) {
|
|
task_manager_exit();
|
|
g_thread_unref(g_pEvLoopThread);
|
|
gtk_main_quit();
|
|
}
|
|
|
|
int cacheDhcpOfferBuffer(PDHCP_INFO pInfo, U8 *pBuf, int size) {
|
|
pInfo->pOfferBuf.p = (U8 *)malloc(size);
|
|
if (pInfo->pOfferBuf.p) {
|
|
memcpy(pInfo->pOfferBuf.p, pBuf, size);
|
|
pInfo->pOfferBuf.buf_size = size;
|
|
return ERR_SUCCESS;
|
|
}
|
|
|
|
return -ERR_MALLOC_MEMORY;
|
|
}
|
|
|
|
int cacheDhcpAckBuffer(PDHCP_INFO pInfo, U8 *pBuf, int size) {
|
|
pInfo->pAckBuf.p = (U8 *)malloc(size);
|
|
if (pInfo->pAckBuf.p) {
|
|
memcpy(pInfo->pAckBuf.p, pBuf, size);
|
|
pInfo->pAckBuf.buf_size = size;
|
|
return ERR_SUCCESS;
|
|
}
|
|
|
|
return -ERR_MALLOC_MEMORY;
|
|
}
|
|
|
|
_Noreturn static void *dhcpThreadCb(void *UNUSED(pData)) {
|
|
U8 *pkg;
|
|
int size = 0;
|
|
PDHCP_INFO pInfo, pTemp;
|
|
struct timeval now;
|
|
|
|
while (TRUE) {
|
|
if (!g_runTask) {
|
|
g_usleep(1000);
|
|
continue;
|
|
}
|
|
|
|
HASH_ITER(hh, g_pDhcpInfo, pInfo, pTemp) {
|
|
switch (pInfo->step) {
|
|
case STEP_BEGIN:
|
|
pInfo->pDiscBuf.p = dhcp_create_discover_req(pInfo, &size);
|
|
|
|
if (pInfo->pDiscBuf.p) {
|
|
pInfo->pDiscBuf.buf_size = size;
|
|
pInfo->step = STEP_DISCOVER;
|
|
pInfo->status = STA_WAIT_START;
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo, tree_view_data_store_upgade);
|
|
}
|
|
break;
|
|
case STEP_DISCOVER:
|
|
if (pInfo->status == STA_WAIT_START) {
|
|
pkg = get_pkg_free_buf();
|
|
|
|
if (pkg) {
|
|
memcpy(pkg, pInfo->pDiscBuf.p, pInfo->pDiscBuf.buf_size);
|
|
|
|
if (pkg_mmap_tx((U8 *)pkg, pInfo->pDiscBuf.buf_size) == pInfo->pDiscBuf.buf_size) {
|
|
pInfo->status = STA_SEND_REQ;
|
|
gettimeofday(&pInfo->pDiscBuf.tm, NULL);
|
|
pInfo->pDiscBuf.snd += 1;
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo,
|
|
tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 1, "User %u host send DHCP Discover\n", pInfo->vni,
|
|
pInfo->hostname);
|
|
}
|
|
}
|
|
} else if (pInfo->status == STA_SEND_REQ) {
|
|
// 处理超时
|
|
gettimeofday(&now, NULL);
|
|
|
|
if (now.tv_sec - pInfo->pDiscBuf.tm.tv_sec > DHCP_STEP_TIMEOUT) {
|
|
if (pInfo->pDiscBuf.snd < DHCP_PKG_RETRY) {
|
|
// 超时重传
|
|
pInfo->status = STA_WAIT_START;
|
|
ADD_LOG_MSG(ZLOG_LEVEL_WARN, 1,
|
|
"User %u host receive DHCP Offer timeout, retry send Discover %d\n",
|
|
pInfo->vni, pInfo->hostname, pInfo->pDiscBuf.snd);
|
|
} else {
|
|
pInfo->status = STA_ERROR;
|
|
vect_push(g_pErrTask, &pInfo->index);
|
|
g_idle_add(upgrade_status_bar_msg, NULL);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_ERROR, 1, "User %u host receive DHCP Offer error, retry %d\n",
|
|
pInfo->vni, pInfo->hostname, pInfo->pDiscBuf.snd);
|
|
}
|
|
}
|
|
} else if (pInfo->status == STA_RECV_NACK) {
|
|
pInfo->status = STA_ERROR;
|
|
vect_push(g_pErrTask, &pInfo->index);
|
|
g_idle_add(upgrade_status_bar_msg, NULL);
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo, tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_ERROR, 1, "User %u host receive DHCP NACK error, retry %d\n", pInfo->vni,
|
|
pInfo->hostname, pInfo->pDiscBuf.snd);
|
|
}
|
|
break;
|
|
case STEP_OFFER:
|
|
if (pInfo->status == STA_RECV_RSP) {
|
|
pInfo->pReqBuf.p = dhcp_create_request_req(pInfo, &size);
|
|
if (pInfo->pReqBuf.p) {
|
|
pInfo->pReqBuf.buf_size = size;
|
|
pInfo->step = STEP_REQUEST;
|
|
pInfo->status = STA_WAIT_START;
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo, tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 1, "User %u host receive DHCP Offer information\n", pInfo->vni,
|
|
pInfo->hostname);
|
|
}
|
|
}
|
|
break;
|
|
case STEP_REQUEST:
|
|
if (pInfo->status == STA_WAIT_START) {
|
|
pkg = get_pkg_free_buf();
|
|
|
|
if (pkg) {
|
|
memcpy(pkg, pInfo->pReqBuf.p, pInfo->pReqBuf.buf_size);
|
|
|
|
if (pkg_mmap_tx((U8 *)pkg, pInfo->pReqBuf.buf_size) == pInfo->pReqBuf.buf_size) {
|
|
pInfo->status = STA_SEND_REQ;
|
|
gettimeofday(&pInfo->pReqBuf.tm, NULL);
|
|
pInfo->pReqBuf.snd += 1;
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo,
|
|
tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 1, "User %u host send DHCP Request\n", pInfo->vni,
|
|
pInfo->hostname);
|
|
}
|
|
}
|
|
} else if (pInfo->status == STA_SEND_REQ) {
|
|
// 处理超时
|
|
gettimeofday(&now, NULL);
|
|
|
|
if (now.tv_sec - pInfo->pReqBuf.tm.tv_sec > DHCP_STEP_TIMEOUT) {
|
|
if (pInfo->pReqBuf.snd < DHCP_PKG_RETRY) {
|
|
// 超时重传
|
|
pInfo->status = STA_WAIT_START;
|
|
ADD_LOG_MSG(ZLOG_LEVEL_WARN, 1,
|
|
"User %u host receive DHCP ACK timeout, retry send Request %d\n",
|
|
pInfo->vni, pInfo->hostname, pInfo->pReqBuf.snd);
|
|
} else {
|
|
pInfo->status = STA_ERROR;
|
|
vect_push(g_pErrTask, &pInfo->index);
|
|
g_idle_add(upgrade_status_bar_msg, NULL);
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo,
|
|
tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_WARN, 1, "User %u host receive DHCP ACK timeout, retry %d\n",
|
|
pInfo->vni, pInfo->hostname, pInfo->pReqBuf.snd);
|
|
}
|
|
}
|
|
} else if (pInfo->status == STA_RECV_NACK) {
|
|
pInfo->status = STA_ERROR;
|
|
vect_push(g_pErrTask, &pInfo->index);
|
|
g_idle_add(upgrade_status_bar_msg, NULL);
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo, tree_view_data_store_upgade);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_WARN, 1, "User %u host receive DHCP NACK timeout, retry %d\n",
|
|
pInfo->vni, pInfo->hostname, pInfo->pReqBuf.snd);
|
|
}
|
|
break;
|
|
case STEP_ACK:
|
|
if (pInfo->status == STA_RECV_RSP) {
|
|
pInfo->step = STEP_END;
|
|
pInfo->status = STA_RECV_RSP;
|
|
vect_push(g_pFinishTask, &pInfo->index);
|
|
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, upgade_task, pInfo, tree_view_data_store_upgade);
|
|
g_idle_add(upgrade_status_bar_msg, NULL);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 1, "User %u host receive DHCP ACK, finished.\n", pInfo->vni,
|
|
pInfo->hostname);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
g_usleep(100);
|
|
}
|
|
|
|
LOG_MSG(debug, "DHCP status mathine exit......\n");
|
|
}
|
|
|
|
static void cleanupDHCPInfo() {
|
|
PDHCP_INFO pInfo, pTemp;
|
|
HASH_ITER(hh, g_pDhcpInfo, pInfo, pTemp) {
|
|
HASH_DEL(g_pDhcpInfo, pInfo);
|
|
if (pInfo->pOfferBuf.p) {
|
|
free(pInfo->pOfferBuf.p);
|
|
}
|
|
|
|
if (pInfo->pDiscBuf.p) {
|
|
free(pInfo->pDiscBuf.p);
|
|
}
|
|
|
|
if (pInfo->pReqBuf.p) {
|
|
free(pInfo->pReqBuf.p);
|
|
}
|
|
|
|
if (pInfo->pAckBuf.p) {
|
|
free(pInfo->pAckBuf.p);
|
|
}
|
|
free(pInfo);
|
|
}
|
|
}
|
|
|
|
static void mainWnd_on_tb_start(GObject *object, gpointer UNUSED(user_data)) {
|
|
int i, j, index = 0;
|
|
GtkTreeIter iter;
|
|
GtkTextIter it, it1;
|
|
PDHCP_INFO pInfo;
|
|
GtkTreeModel *cobModel;
|
|
gchar *pCobText;
|
|
unsigned char mac[6];
|
|
U32 macVal;
|
|
GtkWidget *stopButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStop"));
|
|
GtkWidget *nicSelect = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "cbNicName"));
|
|
GtkWidget *macBegin = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtMacStart"));
|
|
GtkWidget *preHostname = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtHostname"));
|
|
GtkWidget *vniStart = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVni"));
|
|
GtkWidget *numVniCli = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVniClient"));
|
|
GtkWidget *numRequest = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbReqNum"));
|
|
GtkWidget *txLog = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtLogout"));
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txLog));
|
|
const char *strMacBegin = gtk_entry_get_text(GTK_ENTRY(macBegin));
|
|
const char *strPreHostname = gtk_entry_get_text(GTK_ENTRY(preHostname));
|
|
U32 nRequest = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numRequest));
|
|
U32 nVni = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vniStart));
|
|
U32 nVniCnt = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numVniCli));
|
|
|
|
string_mac_to_bytes(strMacBegin, mac);
|
|
macVal = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
|
|
|
|
cleanupDHCPInfo();
|
|
|
|
g_endTask = 0;
|
|
|
|
if (g_pFinishTask) {
|
|
vect_clear(g_pFinishTask);
|
|
}
|
|
|
|
if (g_pErrTask) {
|
|
vect_clear(g_pErrTask);
|
|
}
|
|
|
|
g_pFinishTask = vect_create(nRequest * nVniCnt, sizeof(U32), ZV_SEC_WIPE);
|
|
g_pErrTask = vect_create(nRequest * nVniCnt, sizeof(U32), ZV_SEC_WIPE);
|
|
|
|
for (i = 0; i < nRequest; i++) {
|
|
for (j = 0; j < nVniCnt; j++) {
|
|
U32 macAddr = macVal + index;
|
|
pInfo = (PDHCP_INFO)malloc(sizeof(DHCP_INFO));
|
|
|
|
if (pInfo == NULL) {
|
|
fprintf(stderr, "Malloc %lu bytes memory error of %d\n", sizeof(DHCP_INFO), i);
|
|
continue;
|
|
}
|
|
|
|
memset(pInfo, 0, sizeof(DHCP_INFO));
|
|
pInfo->index = index;
|
|
pInfo->vni = nVni + i;
|
|
pInfo->mac[0] = mac[0];
|
|
pInfo->mac[1] = mac[1];
|
|
pInfo->mac[2] = (macAddr & 0xFF000000) >> 24;
|
|
pInfo->mac[3] = (macAddr & 0xFF0000) >> 16;
|
|
pInfo->mac[4] = (macAddr & 0xFF00) >> 8;
|
|
pInfo->mac[5] = (macAddr & 0xFF);
|
|
|
|
sprintf(pInfo->hostname, "%s_%u", strPreHostname, pInfo->vni + index);
|
|
pInfo->step = STEP_BEGIN;
|
|
pInfo->status = STA_WAIT_START;
|
|
pInfo->close = FALSE;
|
|
HASH_ADD_INT(g_pDhcpInfo, index, pInfo);
|
|
index++;
|
|
}
|
|
}
|
|
|
|
gtk_widget_set_sensitive(GTK_WIDGET(object), FALSE);
|
|
gtk_widget_set_sensitive(nicSelect, FALSE);
|
|
tree_view_data_store_create();
|
|
gtk_widget_set_sensitive(stopButton, TRUE);
|
|
|
|
cobModel = gtk_combo_box_get_model(GTK_COMBO_BOX(nicSelect));
|
|
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(nicSelect), &iter);
|
|
gtk_tree_model_get(cobModel, &iter, 0, &pCobText, -1);
|
|
|
|
dhcp_tools_init_network(pCobText);
|
|
g_runTask = TRUE;
|
|
gettimeofday(&g_StartTm, NULL);
|
|
|
|
gtk_text_buffer_get_start_iter(buffer, &it);
|
|
gtk_text_buffer_get_end_iter(buffer, &it1);
|
|
gtk_text_buffer_delete(buffer, &it, &it1);
|
|
ADD_LOG_MSG(ZLOG_LEVEL_INFO, 0, "Begin test total user: %d, %d host/user\n", nRequest, nVniCnt);
|
|
}
|
|
|
|
static void mainWnd_on_tb_stop(GObject *object, gpointer UNUSED(user_data)) {
|
|
GtkWidget *startButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStart"));
|
|
GtkWidget *nicSelect = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "cbNicName"));
|
|
GtkWidget *tbExpand = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbExpand"));
|
|
|
|
g_runTask = FALSE;
|
|
gtk_widget_set_sensitive(GTK_WIDGET(object), FALSE);
|
|
gtk_widget_set_sensitive(startButton, TRUE);
|
|
gtk_widget_set_sensitive(nicSelect, TRUE);
|
|
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(tbExpand), FALSE);
|
|
g_object_set(G_OBJECT(tbExpand), "stock_id", "gtk-indent", NULL);
|
|
}
|
|
|
|
static void mainWnd_on_tb_expand(GObject *object, gpointer UNUSED(user_data)) {
|
|
GtkWidget *view = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "treeResult"));
|
|
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(object))) {
|
|
gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
|
|
g_object_set(object, "stock_id", "gtk-unindent", NULL);
|
|
} else {
|
|
gtk_tree_view_collapse_all(GTK_TREE_VIEW(view));
|
|
g_object_set(object, "stock_id", "gtk-indent", NULL);
|
|
}
|
|
}
|
|
|
|
static void mainWnd_on_tb_cleanup(GObject *UNUSED(object), gpointer UNUSED(user_data)) {
|
|
GtkTextIter it, it1;
|
|
GtkWidget *view = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "treeResult"));
|
|
GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo"));
|
|
GtkWidget *tbStop = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStop"));
|
|
GtkWidget *txLog = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtLogout"));
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txLog));
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL);
|
|
gtk_tree_store_clear(store);
|
|
cleanupDHCPInfo();
|
|
|
|
mainWnd_on_tb_stop(G_OBJECT(tbStop), NULL);
|
|
|
|
gtk_text_buffer_get_start_iter(buffer, &it);
|
|
gtk_text_buffer_get_end_iter(buffer, &it1);
|
|
gtk_text_buffer_delete(buffer, &it, &it1);
|
|
}
|
|
|
|
static void *uv_loop_thread(void *UNUSED(pData)) {
|
|
task_manager_run();
|
|
return NULL;
|
|
}
|
|
|
|
static GtkTextBuffer *g_pLogTxtBuf = NULL;
|
|
|
|
static gboolean upgrade_gtk_txt_msg(gpointer pInfo) {
|
|
GtkTextIter iter;
|
|
gtk_text_buffer_get_end_iter(g_pLogTxtBuf, &iter);
|
|
gtk_text_buffer_insert(g_pLogTxtBuf, &iter, (const char *)pInfo, -1);
|
|
free(pInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
void write_log_msg(const char *pMsg, int mode) {
|
|
if (g_pLogTxtBuf == NULL) {
|
|
GtkWidget *txLog = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtLogout"));
|
|
g_pLogTxtBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txLog));
|
|
}
|
|
|
|
if (pMsg && strlen(pMsg) > 0 && g_pLogTxtBuf) {
|
|
if (mode == 0) {
|
|
GtkTextIter iter;
|
|
gtk_text_buffer_get_end_iter(g_pLogTxtBuf, &iter);
|
|
gtk_text_buffer_insert(g_pLogTxtBuf, &iter, pMsg, -1);
|
|
} else {
|
|
g_idle_add(upgrade_gtk_txt_msg, (gpointer)pMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int args, char **argv) {
|
|
int i, ret;
|
|
GtkTreeIter iter;
|
|
SYS_NIC_INFO info = {0};
|
|
|
|
if ((ret = zlog_init(ZLOG_CFG_PATH)) != ERR_SUCCESS) {
|
|
printf("Zlog configure file [%s] init result: %d+++++\n", ZLOG_CFG_PATH, ret);
|
|
zlog_profile();
|
|
return -ERR_ZLOG_INIT;
|
|
} else {
|
|
LOG_MOD(debug, ZLOG_MOD_INIT, "Zlog used configure file [%s]\n", ZLOG_CFG_PATH);
|
|
dzlog_init(ZLOG_CFG_PATH, get_cur_process_name());
|
|
}
|
|
|
|
get_all_network_info(&info);
|
|
|
|
gtk_init(&args, &argv);
|
|
load_css();
|
|
|
|
g_mainBuilder = gtk_builder_new();
|
|
gtk_builder_add_from_file(g_mainBuilder, "./res/main.glade", NULL);
|
|
|
|
GtkWidget *mainWnd = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "wndMain"));
|
|
g_signal_connect(mainWnd, "destroy", G_CALLBACK(mainWnd_on_destroy), g_mainBuilder);
|
|
|
|
GtkWidget *txtLog = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtLogout"));
|
|
gtk_widget_set_name(txtLog, "txtLogout");
|
|
|
|
GtkWidget *tbStart = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStart"));
|
|
g_signal_connect(tbStart, "clicked", G_CALLBACK(mainWnd_on_tb_start), g_mainBuilder);
|
|
|
|
GtkWidget *tbStop = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStop"));
|
|
g_signal_connect(tbStop, "clicked", G_CALLBACK(mainWnd_on_tb_stop), g_mainBuilder);
|
|
|
|
GtkWidget *tbExpand = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbExpand"));
|
|
g_signal_connect(tbExpand, "clicked", G_CALLBACK(mainWnd_on_tb_expand), g_mainBuilder);
|
|
|
|
GtkWidget *tbClean = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbCleanup"));
|
|
g_signal_connect(tbClean, "clicked", G_CALLBACK(mainWnd_on_tb_cleanup), g_mainBuilder);
|
|
|
|
GtkWidget *cbNic = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "cbNicName"));
|
|
for (i = 0; i < info.nicCnt; i++) {
|
|
GtkListStore *store = GTK_LIST_STORE(gtk_builder_get_object(g_mainBuilder, "lsNicName"));
|
|
gtk_combo_box_set_model(GTK_COMBO_BOX(cbNic), GTK_TREE_MODEL(store));
|
|
|
|
gtk_list_store_append(store, &iter);
|
|
gtk_list_store_set(store, &iter, 0, info.pNicCtx[i].ethName, -1);
|
|
|
|
if (i == info.nicCnt - 1) {
|
|
gtk_combo_box_set_active(GTK_COMBO_BOX(cbNic), i);
|
|
}
|
|
}
|
|
|
|
if (info.pNicCtx) {
|
|
free(info.pNicCtx);
|
|
}
|
|
|
|
//GtkWidget *macTxt = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtMacStart"));
|
|
|
|
GtkWidget *numInc = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbReqNum"));
|
|
GtkAdjustment *adj = gtk_adjustment_new(1, 1, 100000, 1, 0, 0);
|
|
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(numInc), adj);
|
|
|
|
GtkWidget *numVni = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVni"));
|
|
GtkAdjustment *adjVni = gtk_adjustment_new(1, 0, 10000000, 1, 0, 0);
|
|
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(numVni), adjVni);
|
|
|
|
GtkWidget *numVniCli = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVniClient"));
|
|
GtkAdjustment *adjVniCli = gtk_adjustment_new(1, 1, 1000, 1, 0, 0);
|
|
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(numVniCli), adjVniCli);
|
|
|
|
//GtkWidget *view = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "treeResult"));
|
|
|
|
details_wnd_create(g_mainBuilder);
|
|
//hex_wnd_create(g_mainBuilder);
|
|
//statis_wnd_create(g_mainBuilder);
|
|
#if 0
|
|
gtk_list_store_new(NUM_COLS,
|
|
G_TYPE_INT,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_FLOAT);
|
|
#endif
|
|
|
|
GdkDisplay *display = gdk_display_get_default();
|
|
GdkMonitor *monitor = gdk_display_get_primary_monitor(display);
|
|
GdkRectangle rect;
|
|
gdk_monitor_get_geometry(monitor, &rect);
|
|
|
|
gtk_widget_set_size_request(mainWnd, MAIN_WND_WIDTH, MAIN_WND_HEIGHT); // 设置窗口的最小大小
|
|
gtk_window_move(GTK_WINDOW(mainWnd), (rect.width - MAIN_WND_WIDTH) / 2, (rect.height - MAIN_WND_HEIGHT) / 2);
|
|
|
|
gtk_builder_connect_signals(g_mainBuilder, NULL);
|
|
gtk_widget_show(mainWnd);
|
|
upgrade_status_bar_msg(NULL);
|
|
|
|
g_pEvLoopThread = g_thread_new("uv_loop", uv_loop_thread, NULL);
|
|
g_thread_new("dhcp", dhcpThreadCb, NULL);
|
|
|
|
gtk_main();
|
|
|
|
return 0;
|
|
} |