您的位置:首页 > 其它

开发AP通过snmp获取CPE配置信息并保存到xml显示到web,遇到的问题总结

2015-11-06 19:00 851 查看
开发流程:每个CPE的上线上报都会初始化下面的结构体和链表数据的存储;下面是针对一个CPE上线做的处理,多个CPE上线重复下面操作即可。

数据结构的定义

typedef struct _yh_snmpinfo_head

{

yh_snmpinfo *head; 后面的节点信息用链表的形式存储

char ip[18];

char mac[18];

}yh_snmpinfo_head; 存放ip和mac地址信息和下面的分支数据

typedef struct _yh_snmpinfo

{

yh_info_handle *handlers; 读取oid用于获取oid对应的val

u_char *val;
节点指val

struct _yh_snmpinfo *next; 存储链表的下一个地址

}yh_snmpinfo; 存放cpe的节点信息结构

由于知晓客户端返回的数据的顺序和格式,则可以根据自己定义结构体的内容来直接获取数据到链表中,一一对应,根据顺序解析即可。

typedef struct _yh_info_handle

{

char *parent;

char *child;

u_char *oid;

int type;

}yh_info_handle;

一、CPE上线snmptrap上报及AP端snmpget批量获取cpe配置信息选中所有节点一次性全部获取;获取节点信息函数:

int getValueFromSnmpAgent(snmpinfo_head *info)

{

int len = 0;

char cmd[128] = {0};

char buf[128] = {0};

yh_snmpinfo *snmpinfo = info->head;

for (; snmpinfo; snmpinfo = snmpinfo->next)

{

memset(cmd, 0, 128);

memset(buf, 0, 128);

if (snmpinfo->handlers->oid)

{

sprintf(cmd, "snmpget -v 2c -c public %s %s.%s.0",

info->ip, OID_HEAD, snmpinfo->handlers->oid);

if (snmpinfo->handlers->type == TYPE_INT)

sprintf(cmd, "%s | cut -d ':' -f2 | tr -d ' '", cmd);

else if (snmpinfo->handlers->type == TYPE_STRING)

sprintf(cmd, "%s | cut -d '\"' -f2", cmd);

if (run_popen(cmd, &buf) < 0)

{

return -1;

}

}

if (strcmp(snmpinfo->handlers->child, "ip") == 0)

strcpy(buf, info->ip);

else if (strcmp(snmpinfo->handlers->child, "mac") == 0)

strcpy(info->mac, buf);

len = strlen(buf)+1;

snmpinfo->val = (u_char *)malloc(len);

if (snmpinfo->val == NULL)

return -1;

memset(snmpinfo->val, 0, len);

memcpy(snmpinfo->val, buf, len-1);

}

return 1;

}

二、将获取到的数据存入到结构体中;

定义的结构体如下:

static info_handle snmpinfo_handle[] =

{

{"runstatus",
"ip", NULL, TYPE_STRING},
//ip

{"runstatus",
"mac", "1.1", TYPE_STRING},
//mac

{"runstatus",
"swversion", "1.2", TYPE_STRING},
//swversion

{"runstatus",
"rssi", "1.3", TYPE_STRING},
//rssi

{"runstatus",
"rate", "1.4", TYPE_STRING},
//rate

{"runstatus",
"txbytes", "1.5", TYPE_STRING},
//txbytes

{"runstatus",
"rxbytes", "1.6", TYPE_STRING},
//rxbytes

{"runstatus",
"online", "1.7", TYPE_STRING},
//online

{"runstatus",
"localip", "1.8", TYPE_STRING},
//localip

{"setinfo", "txpower","2.2", TYPE_INT},
//txpower

{"setinfo", "rts","2.3", TYPE_INT},//rts

{"setinfo", "timeoutmode","2.4", TYPE_INT},//timeoutmode

{"setinfo", "uplink","2.5", TYPE_STRING},//qos uplink

{"setinfo", "downlink","2.6", TYPE_STRING},//qos downlink

{"setinfo", "rtstype","2.7", TYPE_STRING},//rts type

{"setinfo", "protmode","2.8", TYPE_INT},//protmode

{"setinfo", "shpreamble","2.9", TYPE_INT},
//shpreamble

{"setinfo", "acktimeout","2.10", TYPE_INT},//acktimeout

{"setinfo", "ctstimeout","2.11", TYPE_INT},//ctstimeout

{"setinfo", "slottimeout","2.12", TYPE_INT},//slottimeout

{"setinfo", "cpedistance","2.13", TYPE_INT},//cpedistance

{"userinfo", "account","3.1", TYPE_STRING},//net account

{"userinfo", "username","3.2", TYPE_STRING},//username

{"userinfo", "tel","3.3", TYPE_STRING},//telephone number

{"userinfo", "address","3.4", TYPE_STRING},//adress

{"userinfo", "attendant","3.5", TYPE_STRING},//matain name

{"userinfo", "atttel","3.6", TYPE_STRING},//matain telephone number

{"userinfo", "longitude","3.7", TYPE_STRING},//matain name

{"userinfo", "latitude","3.8", TYPE_STRING},//matain telephone number

{"userinfo", "remarks","3.9", TYPE_STRING}
//matain telephone number

};

三、将结构体中的数据写入到xml文件中;

root = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);

fseek(fp,0,SEEK_SET);

ftruncate(lock_fd,0);

if (root)

{

cpeinfo = root->child;

mac = mxmlFindElement(cpeinfo, root, cpe->mac, NULL, NULL, MXML_DESCEND);

if (!mac)

{

mac = mxmlNewElement(cpeinfo, cpe->mac);

printf("mac = [%s]\n", cpe->mac);

}

else

{

printf("find mac = [%s]\n", cpe->mac);

update = 1;

}

}

if (update)

{

//group = mxmlFindElement(mac, root, "userinfo", NULL, NULL, MXML_DESCEND);

for (group = mac->child; group; group = group->next)

{

for (node = group->child; node; node = node->next)

{

for (;info;info = info->next)

{

if (strcmp(info->handlers->parent, group->value.element.name)||

strcmp(info->handlers->child, "mac") == 0)

continue;

if (strcmp(node->value.element.name, info->handlers->child) == 0)

{

if (info->val)

{

if (node->child)

mxmlSetText(node, 0, info->val);

else

mxmlNewText(node, 0, info->val);

}

break;

}

}

}

}

}

else

{

pre = info;

for (; info; info = info->next)

{

if (group == NULL ||

strcmp(pre->handlers->parent, info->handlers->parent))

group = mxmlNewElement(mac, info->handlers->parent);

pre = info;

if (group)

{

if (strcmp(info->handlers->child, "mac") == 0)

continue;

node =mxmlNewElement(group, info->handlers->child);

if (info->val)

{

mxmlNewText(node, 0, info->val);

}

}

}

}

当多台设备同时上报,将数据从写入到xml文件的话,会导致同时写入使得文件出错;

解决方法:

在将结构体中的数据写入到xml文件的代码段:使用write锁对代码段加锁;

在web页面从xml获取cpe配置信息时,使用read锁对代码段加锁;

四、集中升级的问题:

1、使用tftp做AP对CPE进行集中升级,30台CPE同时上线,并在AP端写入高版本软件,放在tftpd对应的路径中,查看AP的进程ps以及web页面;

2、出现部分设备升级不成功问题;

解决方法:

1、tftpd添加文件锁,同时只能让一个CPE下载,下载完后才能由下一个CPE去下载;

导致的问题:tftpd程序中进行下载操作时,开辟子进程,子进程复制一份父进程的所有资源,同时进行的时候,无法保证临界资源的同步;不能更好的解决问题,下载速度很慢;

2、改用wget方法,测底解决问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: