openlldp-0.4alpha实现详解(五)——tx_sm模块

7 篇文章 5 订阅

    该模块主要是构建了要传输的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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值