该模块主要是构建了要传输的lldp报文,以及发送状态机的运转。该处实现的bug之一,就是shutdown报文并没有构建正确。且当本地信息发生变化时,并不会将somethingchangelocal置一,这样当本端有变动时,无法将最新的信息尽快的发送给直连邻居。还有当收到一个新的邻居信息时,不会立即进行回应。同时当lldp协议被置为disable时,理应发送shutdown报文。但这里并没有提供在协议已经运行起来后的协议使能控制。即便提供了使能控制,发送的shutdown报文格式也是不正确的。
void mibConstrShutdownLLDPDU(struct lldp_port *lldp_port)
{
/* 2013/11/21 we found the shutdownLLDPDU does not work. no dst and src mac address*/
/* struct lldp_tlv *end_of_lldpdu_tlv = create_end_of_lldpdu_tlv(lldp_port);
//debug_printf(DEBUG_NORMAL, "Would send shutdown!");
if(!validate_end_of_lldpdu_tlv(end_of_lldpdu_tlv))
{
// We only want the first 3 bytes...
// The type/length pair are bytes 1 & 2 (7 and 9 bits respectively)
// The 3rd octect should contain a 0.
memcpy(lldp_port->tx.frame, end_of_lldpdu_tlv, 3);
/*2013/11/21*/
/* lldp_port->tx.sendsize = 3;
printk("ShutdownLLDPDU\n");
}
else
{
//debug_printf(DEBUG_NORMAL, "[ERROR] TLV End of LLDPDU validation faliure in %s() at line: %d!\n", __FUNCTION__, __LINE__);
}
free(end_of_lldpdu_tlv);*/
/*
以下为更正后的代码
*/
// This code will only work for Linux!
struct lldp_ethhdr tx_hdr;
struct lldp_tlv_list *tlv_list = NULL;
struct lldp_flat_tlv *tlv = NULL;
struct lldp_tlv_list *tmp = 0;
uint32_t frame_offset = 0;
// Update our port information so it's current. ;)
// This should be replaced with OS-specific events if possible...
/* 2013/11/21 */
//refreshInterfaceData(lldp_port);
/* As per section 10.3.1, verify the destination and ethertype */
tx_hdr.h_dest[0] = 0x01;
tx_hdr.h_dest[1] = 0x80;
tx_hdr.h_dest[2] = 0xc2;
tx_hdr.h_dest[3] = 0x00;
tx_hdr.h_dest[4] = 0x00;
tx_hdr.h_dest[5] = 0x0e;
tx_hdr.h_source[0] = lldp_port->source_mac[0];
tx_hdr.h_source[1] = lldp_port->source_mac[1];
tx_hdr.h_source[2] = lldp_port->source_mac[2];
tx_hdr.h_source[3] = lldp_port->source_mac[3];
tx_hdr.h_source[4] = lldp_port->source_mac[4];
tx_hdr.h_source[5] = lldp_port->source_mac[5];
tx_hdr.h_lldp_proto = htons(0x88cc);
// How far into our frame should we offset our copies?
frame_offset = 0;
if(lldp_port->tx.frame != NULL)
{
memcpy(&lldp_port->tx.frame[frame_offset], &tx_hdr, sizeof(tx_hdr));
}
frame_offset += sizeof(struct eth_hdr);
/*
lldp shutdown报文仅仅包含必须的4个tlv,且ttl字段被设置为0
*/
// This TLV *MUST* be first.
add_tlv(create_chassis_id_tlv(lldp_port), &tlv_list);/*createº¯ÊýÒÑŸÍê³ÉTLV×Ö¶ÎÏòlldp_portµÄÌíŒÓ*/
// This TLV *MUST* be second.
add_tlv(create_port_id_tlv(lldp_port), &tlv_list);
uint16_t ttl_tmp = lldp_port->tx.txTTL;
lldp_port->tx.txTTL = 0;
// This TLV *MUST* be third.
add_tlv(create_ttl_tlv(lldp_port), &tlv_list);
lldp_port->tx.txTTL = ttl_tmp;
// This TLV *MUST* be last.
add_tlv(create_end_of_lldpdu_tlv(lldp_port), &tlv_list);
tmp = tlv_list;
while(tmp != NULL) { /*flatten_tlv ºÍdestroy_flattened_tlvûÕûÃ÷°×ÕâÊÇÔõÃŽ»ØÊÂ*/
tlv = flatten_tlv(tmp->tlv);
if(lldp_port->tx.frame != NULL)
{
memcpy(&lldp_port->tx.frame[frame_offset], tlv->tlv, tlv->size);
//DEBUG_INFO("mibConstrInfoLLDPDU-while");
}
frame_offset += tlv->size;
destroy_flattened_tlv(&tlv);
tmp = tmp->next;
}
destroy_tlv_list(&tlv_list);
// Pad to 64 bytes
if(frame_offset < 64) {
lldp_port->tx.sendsize = 64;
} else {
lldp_port->tx.sendsize = frame_offset;
}
}
当然如果为了更正本lldp实现版本的错误,还要更改tx_sm状态机的状态跳转函数txGlobalStatemachineRun。其他代码和lldp的标准文档比较一致,这里不做说明了。
本人享有博客文章的版权,转载请标明出处http://blog.csdn.net/baidu20008