开发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方法,测底解决问题。
数据结构的定义
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方法,测底解决问题。
相关文章推荐
- Android ListView的item点击失效解决办法
- 王高利:Linux针对Red Hat Enterprise Linux 6.5 的防火墙详细讲解,iptables(netfilter)规则的
- expect spawn、linux expect 用法
- sql开窗函数 row_number () over(order by id )
- poj3070Fibonacci【矩阵快速幂】
- B. Duff in Love
- 关于Java编程中的一些奇怪的错误(一)——版本冲突
- Daily Scrum (2015/11/5)
- [LeetCode]62. Excel Sheet Column Title Excel列序号
- Java 代码性能优化总结
- CCNP学习笔记1-路由
- 类图(一)
- Blog搬家
- iOS培训第四周第三5天(OC第5讲)
- jsp 取值 从表 几种做法
- 1106文法推导
- 学习linux之用mail命令发邮件
- QWeb、Widget继承
- listview点击事件失效
- Java读取本地文件,然后把数据存到mysql.(以csv文件为例)