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

来源:互联网 发布:新版淘宝0.01元兑在哪 编辑:程序博客网 时间:2024/04/27 13:43

开发流程:每个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方法,测底解决问题。

0 0
原创粉丝点击