openlldp-0.4alpha实现详解(二)

接下来,看看openlldp的源代码src目录:


这其中,platform目录包含了各种不同平台收发报文和获取网络接口信息的接口,主要是bpf和linux的。tlv模块包含了lldpdu中报文的创建,验收,销毁等等工作。lldp_debug模块包含了调试信息打印接口。lldp_neighbor模块包含了获取系统信息以及提取lldp邻居信息接口。lldpneighbors模块为查看邻居信息的小工具。msap模块则包含了邻居信息的创建,更新和增加接口。rx_sm模块和tx_sm模块为接收和发送端口状态机的实现,lldp_main模块通过对于定时对接收和发送状态机接口的调用实现lldp协议的运转。

各种数据结构定义如下:

struct lldp_port {	/*端口数据结构为链表*/
  struct lldp_port *next;
  int socket;        // The socket descriptor for this interface.
  /*该接口的发送接收所使用到的套接字*/
  char *if_name;     // The interface name.
  /*网卡接口名*/
  uint32_t if_index; // The interface index.
  /*网卡索引*/
  uint32_t mtu;      // The interface MTU.
  /*mtu*/
  uint8_t source_mac[6];
  /*源MAC地址,也即本机网卡的MAC地址*/
  uint8_t source_ipaddr[4];
  /*源IP地址,本机的IP地址*/
  struct lldp_rx_port rx;
  /*发送端口*/
  struct lldp_tx_port tx;
  /*接收端口*/
  uint8_t portEnabled;
  /*端口使能*/
  uint8_t adminStatus;
  /*端口状态*/
  /* I'm not sure where this goes... the state machine indicates it's per-port */
  uint8_t rxChanges;
  
  // I'm really unsure about the best way to handle this... 
  uint8_t tick;
  time_t last_tick;
  
  struct lldp_msap *msap_cache;


  // 802.1AB Appendix G flag variables.
  uint8_t  auto_neg_status;
  uint16_t auto_neg_advertized_capabilities;
  uint16_t operational_mau_type;
};

每个网络接口都对应了这样一个数据结构,它用来存储网络接口的接口名,接口索引,mac地址,创建的套接字描述符,和邻居信息指针(这里问lldp_msap)以及最为重要的接收和发送端口缓存(具体为lldp_rx_port结构体和lldp_tx_port结构体)等等。


struct lldp_tx_port {
    uint8_t *frame;    /**< The tx frame buffer */
    uint64_t sendsize; /**< The size of our tx frame */
    uint8_t state;     /**< The tx state for this interface */
    uint8_t somethingChangedLocal; /**< IEEE 802.1AB var (from where?) */
    uint16_t txTTL;/**< IEEE 802.1AB var (from where?) */
    struct lldp_tx_port_timers timers; /**< The lldp tx state machine timers for this interface */
    struct lldp_tx_port_statistics statistics; /**< The lldp tx statistics for this interface */
};

该结构体为存储发送缓存以及发送端口状态机相关参数。其中,frame为缓存发送报文的指针,sendsize为待发送的缓存字节数。其他一些参数则是和tx状态机相关的变量。它们在收发报文时,被改变,从而影响了发送状态机的运转轨迹。somethingChangedLocal在本端信息改变时被置位。它被置一标志着lldp开启快速发送机制,会将本端信息快速的传递给直连邻居。


struct lldp_rx_port {	
    uint8_t *frame;
    ssize_t recvsize;
    uint8_t state;
    uint8_t badFrame;
    uint8_t rcvFrame;
    uint8_t rxInfoAge;
    uint8_t somethingChangedRemote;
    uint8_t tooManyNeighbors;
    struct lldp_rx_port_timers timers;
    struct lldp_rx_port_statistics statistics;
};
这个结构体和上面的类似,只不过这个缓存的是接收报文。somethingChangedRemote为接收邻居信息后,发现邻居信息有改变则将其置一。

struct lldp_msap {
  struct lldp_msap *next;
  uint8_t *id;
  uint8_t length;
  struct lldp_tlv_list *tlv_list;
  
  // XXX Revisit this
  // A pointer to the TTL TLV
  // This is a hack to decrement
  // the timer properly for 
  // lldpneighbors output
  struct lldp_tlv *ttl_tlv;

  /* IEEE 802.1AB MSAP-specific counters */
  uint16_t rxInfoTTL;
};

这个数据结构主要是存储一条邻居信息。多个邻居信息,则以链表的形式组织在lldp_port结构体中。id为lldpdu中必填的tlv字段的chassis subtype id和 port subtype id组成。基本上不同的邻居信息会有不同的lldp_msap id。length为经过格式化之后的全部lldp报文tlv长度。rxInfoTTL则为老化时间。tlv_list为存储tlv的链表,每个节点是一个tlv。该tlv经过了“格式化”而非lldpdu中的tlv。只有经过了什么样的格式化,后续会讲述。


struct lldp_tlv_list {
    struct lldp_tlv_list *next;
    struct lldp_tlv *tlv;
};

tlv为一条lldp的tlv,多个tlv被组织为链表的形式。

struct lldp_tlv {
    uint8_t  type;
    uint16_t length;
    uint8_t  *info_string;
};

tlv的数据结构定义,严格的T(type) L(length)V(value)形式。

所以,总的来说,该系统中关键数据结构的组织如下图,就是链表套链表,链表再套链表的形式。

openlldp-0.4alpha实现详解(二)_第1张图片


本人享有博客文章的版权,转载请标明出处http://blog.csdn.net/baidu20008

你可能感兴趣的:(LLDP,实现详解)