LLDP/CDP状态上报

一、LLDP/CDP简介

链路层发现协议(LLDP):LLDP使设备能够向相邻设备通告其标识、配置和功能,这些设备随后将数据存储在管理信息库(MIB)中。 邻居之间共享的信息有助于缩短将新设备添加到局域网(LAN)所需的时间,并提供排除许多配置问题所需的详细信息。LLDP可用于需要在非思科专有设备和思科专有设备之间工作的场景。交换机提供有关端口当前LLDP状态的所有信息,您可以使用此信息修复网络中的连接问题。这是网络发现应用(如FindIT网络管理)用于发现网络中设备的协议之一。
LLDP和思科发现协议(CDP)都是相似的协议,区别在于LLDP可促进供应商互操作性,而CDP是思科专有协议

二、LLDP/CDP本地验证

1. adb remount 然后 adb reboot
2. adb shell mkdir -p /sdcard/Download/lldpd/bin
adb push build/install/vendor/bin/lldpcli /sdcard/Download/lldpd/bin/lldpcli
adb push build/install/vendor/bin/lldpd /sdcard/Download/lldpd/bin/lldpd
adb shell mkdir -p /sdcard/Download/lldpd/lib
adb push build/install/vendor/lib/liblldpctl.so /sdcard/Download/lldpd/lib/liblldpctl.so
3. adb shell
mount -o rw,remount /vendor
mv /sdcard/Download/lldpd/bin/lldpcli /vendor/bin/lldpcli
chmod 755 /vendor/bin/lldpcli
chown root:shell /vendor/bin/lldpcli
mv /sdcard/Download/lldpd/bin/lldpd /vendor/bin/lldpd
chmod 755 /vendor/bin/lldpd
chown root:shell /vendor/bin/lldpd
mv /sdcard/Download/lldpd/lib/liblldpctl.so /vendor/lib/liblldpctl.so
chmod 644 /vendor/lib/liblldpctl.so
chown root:root /vendor/lib/liblldpctl.so
mount -o ro,remount /vendor
4. mkdir /data/data/lldpd/
5. lldpd
6. lldpcli

三,集成系统

#device/rockchip/common/init.connectivity.rc
#增加如下内容
#for lldp
on post-fs-data
   #for lldp
    mkdir /data/data/lldpd 0777 system system
    
    chmod 755 /vendor/bin/lldpcli
    chmod 755 /vendor/bin/lldpd
    chmod 644 /vendor/lib/liblldpctl.so
    chown root shell /vendor/bin/lldpcli
    chown root shell /vendor/bin/lldpd
    chown root system /vendor/lib/liblldpctl.so
    #start lldpd
    

on property:sys.dten.lldp.check.start=1
   start lldp_check_service
service lldp_check_service /system/bin/sh /system/bin/lldp_check.sh &
    class main
    user root
    group root
    disabled
    oneshot
    seclabel u:r:shell:s0

on property:vendor.lldpd.start=1
   start lldpd1
service lldpd1 /vendor/bin/sh /vendor/bin/start_lldpd.sh &
    class main
    user root
    group shell
    disabled
    oneshot
    seclabel u:r:shell:s0

start_lldpd.sh脚本如下,注意,一定要在linux环境下编辑shell脚本,否则会有格式或者其他异常,本人开始使用window创建的sh脚本,结果遇到很多问题,首先sleep执行都不生效。另外Android shell 脚本需要输出日志到

#!/system/bin/sh
sleep 5
log -p i -t "franc" "test lldpd2"
/vendor/bin/lldpd &
log -p i -t "franc" "test lldpd1"
sleep 10000

到logcat,则使用log -p -i -t “tag” “test” 指令。
这里需要注意,因为lldpd服务需要data/data/下面创建lldpd文件目录,而/data/data下有PackageMs维护的安装应用的目录,所以PackageMs在开机会check该目录,因为我们lldpd不是PackageMs可识别的目录,所以会清掉该目录,因此需要在PackageMs中过滤这个check

private void assertPackageKnownAndInstalled(String volumeUuid, String packageName, int userId)   
        throws PackageManagerException {
    
    
    synchronized (mLock) {
    
    
        // Normalize package name to handle renamed packages                                     
        packageName = normalizePackageNameLPr(packageName);                                      
        if("lldpd".equals(packageName)){
    
    
           Slog.i(TAG, "lldpd need the /data/data/lldpd to create socket, so ignore this check");
           return;
        }
        final PackageSetting ps = mSettings.getPackageLPr(packageName);                          
        if (ps == null) {
    
                                                                            
            throw new PackageManagerException("Package " + packageName + " is unknown");         
        } else if (!TextUtils.equals(volumeUuid, ps.volumeUuid)) {
    
                                   
            throw new PackageManagerException(
                    "Package " + packageName + " found on unknown volume " + volumeUuid          
                            + "; expected volume " + ps.volumeUuid);                             
        } else if (!ps.getInstalled(userId)) {
    
    
            throw new PackageManagerException(
                    "Package " + packageName + " not installed for user " + userId);             
        }
    }
}

四、lldp状态检查和上报

lldp的状态检查可以通过java来完成,也可以通过sh脚本来完成,通过考虑sh脚本的方便性,这里通过sh脚本来实现,具体实现脚本如下:

#!system/bin/sh

function print_line(){
    
    
   printf "%s\n" "$*" >> $LLDP_LOG
}

function inquire_connected_interface_info(){
    
        
   #连接是哪个interface,例如wlan0,或者eth0
   CONNECTED_INTERFACE=`/vendor/bin/getprop sys.dten.connected.interface`
   
   #如果CONNECTED_INTERFACE为null,表示还没有连网,此时默认查询wlan0的状态信息
   if [ -z "${CONNECTED_INTERFACE}" ]; then
      print_line "connected interface is null, so set the default value, wlan0"
      CONNECTED_INTERFACE="wlan0"
   fi
      
   print_line " connected interface is  ${CONNECTED_INTERFACE}"

   #将查询结果保存到指定目录文件
   /vendor/bin/lldpcli show interface > ${LLDP_PATH}/lldp_interface_list_tmp.txt
   LLDP_INTERFACE_LIST="${LLDP_PATH}/lldp_interface_list_tmp.txt"
   chmod 777 ${LLDP_INTERFACE_LIST}

   #interface和port descr相同,因此通过查询到interface,可以确认到该interface开机到PORT_DESCR_LINE之间的行
   #而每个interface的classis id和port id正好在这之间
   INTERFACE="Interface\:    ${CONNECTED_INTERFACE}"
   INTERFACE_LINE=`sed -n "{/${INTERFACE}/=}" ${
     
     LLDP_INTERFACE_LIST}`
   print_line "INTERFACE_LINE is ${INTERFACE_LINE}"
   
   PORT_DESCR="PortDescr\:    ${CONNECTED_INTERFACE}"
   PORT_DESCR_LINE=`sed -n "{/${PORT_DESCR}/=}" ${
     
     LLDP_INTERFACE_LIST}`
   print_line "PORT_DESCR_LINE is ${PORT_DESCR_LINE}"
   
   #查找chasss id 
   sed -n "${INTERFACE_LINE},${PORT_DESCR_LINE}{/ChassisID\:/p}" ${LLDP_INTERFACE_LIST} > ${LLDP_PATH}/chassis_id_tmp.txt
   CHASSIS_ID="${LLDP_PATH}/chassis_id_tmp.txt"
   CHASSIS_ID_VALUE=`awk -Fmac '{print $2}' ${
     
     CHASSIS_ID}`
   print_line "CHASSIS_ID_VALUE is ${CHASSIS_ID_VALUE}"
   setprop sys.dten.lldp.chassis_id ${CHASSIS_ID_VALUE}
   sleep 1

   #查找port id
   sed -n "${INTERFACE_LINE},${PORT_DESCR_LINE}{/PortID\:/p}" ${LLDP_INTERFACE_LIST} > ${LLDP_PATH}/port_id_tmp.txt
   PORT_ID="${LLDP_PATH}/port_id_tmp.txt"
   PORT_ID_VALUE=`awk -Fmac '{print $2}' ${
     
     PORT_ID}`
   print_line "PORT_ID_VALUE is ${PORT_ID_VALUE}"
   setprop sys.dten.lldp.port_id ${PORT_ID_VALUE}
   sleep 1

   #判断这次查询和上次查询是否一致,如果一直说明chassis和port id没有改变,不发送广播,否则发送对应的广播
   if [ "${CHASSIS_ID_VALUE}" != "${CHASSIS_ID_LAST_VALUE}" -o "${PORT_ID_VALUE}" != "${PORT_ID_LAST_VALUE}" ]; then
      print_line "chassis id or port id changes, send broadcast to notify this changes"
      #发送广播给系统,这里不直接发给Teams,是因为Teams要求chassis id 和 port id 必须byte数组,而shell不好处理 byte值,
      #因此,通过系统在转一次
      #注意调用am命令,必须要将脚本放到system/bin下,否则am会执行失败
      /system/bin/am broadcast -a dten.intent.action.LLDP_CHANGES_INFO -f 0x01000000 --es chassis_id "${CHASSIS_ID_VALUE}" --es port_id "${PORT_ID_VALUE}"
      if [ "$?" != 0 ]; then
          print_line  "send broadcast failed, maybe your sh file is not in system/bin"
      fi
      
      #最后更新上一次的chassis id和port id
      CHASSIS_ID_LAST_VALUE=${CHASSIS_ID_VALUE}
      PORT_ID_LAST_VALUE=${PORT_ID_VALUE}
      sleep 10
   fi
   
   sleep 1

}

#进入主方法,开始工作,具体每隔5s检测一次lldpd服务的状态以及chassis id 和 port id信息
function main_loop(){
    
    
while true
   do
       #-v参数可以去除自身的查询
       ps -ef |egrep lldpd| egrep -v egrep| egrep -v start_lldpd
       #获取上面命令执行的结果,RK板子R10基线上:1返回没有找到,0表示有找到
       LLDPD_STATUS=$?
       print_line "lldpd status is ${LLDPD_STATUS}"
       #1、检查lldpd服务是否在运行,如果不运行则启动服务
       if [ ${LLDPD_STATUS} -gt 0 ]; then
          print_line "lldpd is stoped, try restart"
          setprop sys.dten.lldpd.start 1
       else
          print_line "lldpd is running, wait 5 sec until next check"
          
          #2、查询lldpd对应连接的chassis id和port id
          inquire_connected_interface_info
       fi

       sleep 5
   done
}


#创建日志和临时文件目录,并赋予权限
mkdir -p /data/lldp/
chmod 777 /data/lldp/

LLDP_PATH="/data/lldp"

LLDP_LOG=${LLDP_PATH}/lldp_check_`date -u +%Y-%m-%d`.log
print_line " "
print_line "~~~~`date -u +%Y-%m-%d_%H%M%S_%Z`~~~~"

#保存上一次查询chassis id, 默认为" "
CHASSIS_ID_LAST_VALUE=" "
PORT_ID_LAST_VALUE=" "

#进入主循开始工作
main_loop

思路也是比较简单,具体如下:

  • 脚本服务进来后,进入主循环,首先check服务是否起来,如果已经起来直接查询,如果没有起来,则启动服务,5s循环一次。
  • 查询逻辑是这样的:首先获取当前连接的interface,例如是wlan0还是eth0,然后通过lldpcli show interfacea获取的每个interface的信息,并保存到/data/lldp/lldp_interface_list_tmp.txt;其次,通过sed命令定位到interface和portdescr所在的行号,在这两者之间找对应的chassidID和portid;最后判断这次查询和上次是否一致,即chassidID或者portid有没有变化,如果有变化咋通过am命令发送广播。

需要注意的有以下几点:

  1. 写的sh脚本必须在Linux环境下,或者类似于cygwin这样的Linux唤醒,否则即使在简单的指令也有可能由于格式问题执行失败;
  2. 我们的写的native服务如果需要常驻,即作为守护进程,需要在服务起来后,做一个死循环,在循环里面做该做的事情,否则代理服务退出后,该服务也将被退出;如果native服务不是我们自己写的,可以通过起脚本,脚本在最后启动完服务后,sleep xxxxxx 防止服务退出;
  3. initrc启动sh脚本服务,如果需要访问类似于system/bin下的am,pm等等指令,脚本文件一定要放到system/bin,否则执行命令会失败

lldp_check脚本发送广播后,在DMServices中接收,然后将其转换为byte数组,发送给Teams,这里没有直接通过脚本发送给Teams的原因是因为sh脚本里面处理byte数组不好处理。

//cfliu add for lldp        //framew
private static final String ACTION_LLDP_INFO = "dten.intent.action.LLDP_CHANGES_INFO";
private static final String ACTION_LLDP_TEAMS_INFO = "com.microsoft.skype.teams.ipphone.partner.SHARE_LLDP_INFO";
//cfliu add for lldp                                                                           
else if(ACTION_LLDP_INFO.equals(intent.getAction())) {
    
                                             
    String chassisIDStr = intent.getStringExtra("chassis_id");                                 
    String portIDStr = intent.getStringExtra("port_id");                                       
    Slog.i(TAG,"receive the lldp info chassis id is "+chassisIDStr+" , port id is "+portIDStr);
    byte[] chassisID = chassisIDStr.getBytes();                                                
    byte[] portID = portIDStr.getBytes();                                                      

    //tell the teams lldp changes
    Intent lldpIntent = new Intent(ACTION_LLDP_TEAMS_INFO);                                    
    lldpIntent.putExtra("CHASSIS_ID", chassisID);
    lldpIntent.putExtra("PORT_ID", portID);
    lldpIntent.addFlags(0x01000000);
    mContext.sendBroadcastAsUser(lldpIntent, UserHandle.ALL);
}

网络连接后,会在ConnectivityService中发送连接成功的广播,这里通过type来判断是那种网络类型,WiFi对应TYPE_WIFI,有线网对应TYPE_ETHERNET。这里需要注意的是Android 12后很多服务放到package/modules下,ConnectivityService引用其他jar包里面也包含SystemProperties类,但是没有set方法,这里通过调用DtenMS的接口来设置属性。

//cfliu add for lldp 20220824                                                
final DXXManager dxxManager = mService.getDXXManager();                   
if(ConnectivityManager.TYPE_WIFI == type){
    
                                       
    if(dxxManager !=null){
    
                                                      
        dxxManager.setProperty("sys.dten.connected.interface", "wlan0");    
        Log.i(TAG, " Connected with WiFi and lldp will check wlan0 success");
    }                                                                        
}else if(ConnectivityManager.TYPE_ETHERNET == type){
    
                             
   if(dxxManager !=null){
    
                                                       
       dxxManager.setProperty("sys.dten.connected.interface", "eth0");      
       Log.i(TAG, " Connected with WiFi and lldp will check eth0 success");  
    }                                                                        
}                                                                            
/end                                                                         

五、lldpd状态测试

//连接XXX-5G
-------------------------------------------------------------------------------
Interface:    wlan0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac f6:3c:5e:80:ee:ad
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.201.52
    MgmtIface:    9
    MgmtIP:       fe80::f43c:5eff:fe80:eead
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 08:fb:ea:ff:b9:b8
    PortDescr:    wlan0
  TTL:          120
-------------------------------------------------------------------------------
  
//连接P30  
-------------------------------------------------------------------------------
Interface:    wlan0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac f6:3c:5e:80:ee:ad
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.43.102
    MgmtIface:    9
    MgmtIP:       fe80::f43c:5eff:fe80:eead
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 08:fb:ea:ff:b9:b8
    PortDescr:    wlan0
  TTL:          120
-------------------------------------------------------------------------------

//重启后连接P30
-------------------------------------------------------------------------------
Interface:    wlan0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac 7a:50:2f:6d:31:0a
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.43.102
    MgmtIface:    9
    MgmtIP:       fe80::d6f0:8109:aa24:8b15
    MgmtIface:    9
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 08:fb:ea:ff:b9:b8
    PortDescr:    wlan0
  TTL:          120
-------------------------------------------------------------------------------

//切换为有线网
-------------------------------------------------------------------------------
Interface:    eth0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac 7a:50:2f:6d:31:0a
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.101.40
    MgmtIface:    7
    MgmtIP:       fe80::a9fc:224:3d0c:9c7d
    MgmtIface:    7
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 50:de:19:e0:c3:15
    PortDescr:    eth0
  TTL:          120
-------------------------------------------------------------------------------

//恢复出厂设置后,连接ethernet
-------------------------------------------------------------------------------
Interface:    eth0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac ce:71:d1:c2:46:7c
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.101.40
    MgmtIface:    7
    MgmtIP:       fe80::cc71:d1ff:fec2:467c
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 50:de:19:e0:c3:15
    PortDescr:    eth0
  TTL:          120
-------------------------------------------------------------------------------

//回厂后,连接到P30
-------------------------------------------------------------------------------
Interface:    wlan0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac ce:71:d1:c2:46:7c
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #20 SMP PREEMPT Tue Aug 23 20:00:08 CST 2022 armv8l
    MgmtIP:       192.168.43.102
    MgmtIface:    9
    MgmtIP:       fe80::cc71:d1ff:fec2:467c
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 08:fb:ea:ff:b9:b8
    PortDescr:    wlan0
  TTL:          120
-------------------------------------------------------------------------------

从以上测试得出以下结论:

  1. 连接不同SSID,LLDP中ChassisID和PortID不变
  2. 回厂后连接相同SSID,ChassisID改变,PortID不变,也就是说回厂后ChassisID会发生变化
  3. 重启后连接相同SSID,ChassisID改变,PortID不变,也就是说回厂后ChassisID会发生变化
  4. 切换到ethernet后,port id会发生变化,ChassisID不变

六、微软上报状态改动

微软要求ChassisID和switch mac地址一致。需要通过lldpcli show neighbors指令替换lldpcli show interface。因此脚本修改如下:

#!system/bin/sh

function print_line(){
    
    
    printf "%s\n" "$*" >> ${
    
    LLDP_LOG}
}

function inquire_connected_interface_info(){
    
    
   #连接是哪个interface,例如wlan0,或者eth0
   CONNECTED_INTERFACE=`/vendor/bin/getprop sys.dten.connected.interface`
   
   #如果CONNECTED_INTERFACE为null,表示还没有连网,此时默认查询wlan0的状态信息
   if [ -z "${CONNECTED_INTERFACE}" ]; then
      print_line "connected interface is null, so set the default value, wlan0"
      CONNECTED_INTERFACE="wlan0"
   fi
      
   print_line " connected interface is  ${CONNECTED_INTERFACE}"

   #将查询结果保存到指定目录文件
   /vendor/bin/lldpcli show neighbor > ${
    
    LLDP_PATH}/lldp_neighbor_list_tmp.txt
   LLDP_NEIGHBOR="${LLDP_PATH}/lldp_neighbor_list_tmp.txt"
   chmod 777 ${
    
    LLDP_NEIGHBOR}

   cat ${
    
    LLDP_PATH}/lldp_neighbor_list_tmp.txt | tr  -d ' ' > ${
    
    LLDP_PATH}/t2.txt
   cat ${
    
    LLDP_PATH}/t2.txt | tr  '\n' '|' > ${
    
    LLDP_PATH}/t3.txt
   sed -i 's/-------------------------------------------------------------------------------/*/g' ${LLDP_PATH}/t3.txt

  sss=`cat ${LLDP_PATH}/t3.txt`
  print_line "ssss:  $sss"
  OLD_IFS="$IFS"
  IFS="*"
  array=($sss)
  IFS="$OLD_IFS"
  CHASSIS_ID_VALUE=" "
  PORT_ID_VALUE=" "
  for var in ${array[@]}
  do
      echo $var > ${LLDP_PATH}/t5.txt
      l=`grep -c localhost ${LLDP_PATH}/t5.txt`
      c=`grep -c ChassisID ${LLDP_PATH}/t5.txt`
      s=`grep -c SysName ${LLDP_PATH}/t5.txt`
      p=`grep -c PortID ${LLDP_PATH}/t5.txt`
      print_line "$l,$c,$s,$p"

      if [ $l  == 0  -a  $c == 1 -a  $s == 1 -a $p == 1 ]; then
        cat ${LLDP_PATH}/t5.txt | tr '|' '\n' > ${LLDP_PATH}/r.txt
        grep ChassisID ${LLDP_PATH}/r.txt > ${LLDP_PATH}/chassis_id.txt
        grep PortID ${LLDP_PATH}/r.txt > ${LLDP_PATH}/port_id.txt
        CHASSIS_ID_VALUE=`awk -FID: '{print $2}' ${LLDP_PATH}/chassis_id.txt`
        PORT_ID_VALUE=`awk -F: '{print $2}' ${LLDP_PATH}/port_id.txt`
        print_line "${CHASSIS_ID_VALUE}  ${PORT_ID_VALUE}"
        break
     fi

  done
   #判断这次查询和上次查询是否一致,如果一直说明chassis和port id没有改变,不发送广播,否则发送对应的广播
   if [ "${CHASSIS_ID_VALUE}" != "${CHASSIS_ID_LAST_VALUE}" -o "${PORT_ID_VALUE}" != "${PORT_ID_LAST_VALUE}" ]; then
      print_line "chassis id , port id, chassis_sub_type or port_sub_type changes, send broadcast to notify this changes"
      #发送广播给系统,这里不直接发给Teams,是因为Teams要求chassis id 和 port id 必须byte数组,而shell不好处理 byte值,
      #因此,通过系统在转一次
      #注意调用am命令,必须要将脚本放到system/bin下,否则am会执行失败
      /system/bin/am broadcast -a dten.intent.action.LLDP_CHANGES_INFO -f 0x01000000 --es chassis_id "${CHASSIS_ID_VALUE}" --es port_id "${PORT_ID_VALUE}"
      if [ "$?" != 0 ]; then
          print_line  "send broadcast failed, maybe your sh file is not in system/bin"
      fi
      
      #最后更新上一次的chassis id和port id
      CHASSIS_ID_LAST_VALUE=${CHASSIS_ID_VALUE}
      PORT_ID_LAST_VALUE=${PORT_ID_VALUE}
      sleep 1
   fi
   sleep 1
}
#进入主方法,开始工作,具体每隔5s检测一次lldpd服务的状态以及chassis id 和 port id信息
function main_loop(){
while true
   do
       #-v参数可以去除自身的查询
       ps -ef |egrep lldpd| egrep -v egrep| egrep -v start_lldpd
       #获取上面命令执行的结果,RK板子R10基线上:1返回没有找到,0表示有找到
       LLDPD_STATUS=$?
       print_line "lldpd status is ${LLDPD_STATUS}"
       #1、检查lldpd服务是否在运行,如果不运行则启动服务
       if [ ${LLDPD_STATUS} -gt 0 ]; then
          print_line "lldpd is stoped, try restart"
          setprop sys.dten.lldpd.start 1
       else
          print_line "lldpd is running, wait 5 sec until next check"
          
          #2、查询lldpd对应连接的chassis id和port id
          inquire_connected_interface_info
       fi

       sleep 5
   done
}


#创建日志和临时文件目录,并赋予权限
mkdir -p /data/lldp/
chmod 777 /data/lldp/

LLDP_PATH="/data/lldp"

LLDP_LOG=${LLDP_PATH}/lldp_check_`date -u +%Y-%m-%d`.log
print_line " "
print_line "~~~~`date -u +%Y-%m-%d_%H%M%S_%Z`~~~~"

#保存上一次查询chassis id, 默认为" "
CHASSIS_ID_LAST_VALUE=" "
PORT_ID_LAST_VALUE=" "
CHASSIS_SUB_TYPE_LAST_VALUE=" "
PORT_SUB_TYPE_LAST_VALUE=" "

#进入主循开始工作
main_loop

DMService中收到广播代码处理片段的处理:

//cfliu add for lldp
private static final String ACTION_LLDP_INFO = "xxxx.intent.action.LLDP_CHANGES_INFO";
private static final String ACTION_LLDP_TEAMS_INFO = "com.microsoft.skype.teams.ipphone.partner.SHARE_LLDP_INFO";
private static final int LLDP_PORTID_SUBTYPE_UNKNOWN = 0;
private static final int LLDP_PORTID_SUBTYPE_IFALIAS = 1;
private static final int LLDP_PORTID_SUBTYPE_PORT = 2;
private static final int LLDP_PORTID_SUBTYPE_LLADDR = 3;
private static final int LLDP_PORTID_SUBTYPE_ADDR = 4;
private static final int LLDP_PORTID_SUBTYPE_IFNAME = 5;
private static final int LLDP_PORTID_SUBTYPE_AGENTCID = 6;
private static final int LLDP_PORTID_SUBTYPE_LOCAL = 7;

private static final int LLDP_CHASSISID_SUBTYPE_CHASSIS = 1;
private static final int LLDP_CHASSISID_SUBTYPE_IFALIAS = 2;
private static final int LLDP_CHASSISID_SUBTYPE_PORT = 3;
private static final int LLDP_CHASSISID_SUBTYPE_LLADDR = 4;
private static final int LLDP_CHASSISID_SUBTYPE_ADDR = 5;
private static final int LLDP_CHASSISID_SUBTYPE_IFNAME = 6;
private static final int LLDP_CHASSISID_SUBTYPE_LOCAL = 7;

//cfliu add for lldp
else if(ACTION_LLDP_INFO.equals(intent.getAction())) {
    
    
    String chassisIDStr = intent.getStringExtra("chassis_id");
    String portIDStr = intent.getStringExtra("port_id");

    // String chassisIDUpCassStr = chassisIDStr.toUpperCase();
    // String portIDUpCassStr = portIDStr.toUpperCase();

    // 处理chassis subtype
    int lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_CHASSIS;
    if (chassisIDStr.startsWith("local")) {
    
    
        chassisIDStr = chassisIDStr.substring(5);
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_LOCAL;
    } else if (chassisIDStr.startsWith("ifname")) {
    
    
        chassisIDStr = chassisIDStr.substring(6);
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_IFNAME;
    } else if (chassisIDStr.startsWith("ifalias")) {
    
    
        chassisIDStr = chassisIDStr.substring(7);
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_IFALIAS;
    } else if (chassisIDStr.startsWith("ip")) {
    
    
        chassisIDStr = chassisIDStr.substring(2);
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_ADDR;
    } else if (chassisIDStr.startsWith("mac")) {
    
    
        chassisIDStr = chassisIDStr.substring(3).toUpperCase();
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_LLADDR;
    } else {
    
    
        lldpChassisSubType = LLDP_CHASSISID_SUBTYPE_CHASSIS;
    }

    int lldpPortSubType = LLDP_PORTID_SUBTYPE_UNKNOWN;
    if (portIDStr.startsWith("local")) {
    
    
        portIDStr = portIDStr.substring(5);
        lldpPortSubType = LLDP_PORTID_SUBTYPE_LOCAL;
    } else if (portIDStr.startsWith("IFNAME")) {
    
    
        portIDStr = portIDStr.substring(6);
        lldpPortSubType = LLDP_PORTID_SUBTYPE_IFNAME;
    } else if (portIDStr.startsWith("IFALIAS")) {
    
    
        portIDStr = portIDStr.substring(7);
        lldpPortSubType = LLDP_PORTID_SUBTYPE_IFALIAS;
    } else if (portIDStr.startsWith("IP")) {
    
    
        portIDStr = portIDStr.substring(2);
        lldpPortSubType = LLDP_PORTID_SUBTYPE_ADDR;
    } else if (portIDStr.startsWith("MAC")) {
    
    
        portIDStr = portIDStr.substring(3).toUpperCase();
        lldpPortSubType = LLDP_PORTID_SUBTYPE_LLADDR;
    } else {
    
    
        lldpPortSubType = LLDP_PORTID_SUBTYPE_UNKNOWN;
    }
    String correlationIDStr = generateGUID();
    String correlationIDUpCassStr = correlationIDStr.toUpperCase();
    Slog.i(TAG,
           "receive the lldp info CHASSIS_ID: " + chassisIDStr + " PORT_ID: "
           + portIDStr
           + " CHASSIS_SUB_TYPE: " + lldpChassisSubType
           + " PORT_SUB_TYPE: " + lldpPortSubType
           + " CORRELATION_ID: " + correlationIDUpCassStr);
    byte[] chassisID = chassisIDStr.getBytes();
    byte[] portID = portIDStr.getBytes();

    // tell the teams lldp changes
    Intent lldpIntent = new Intent(ACTION_LLDP_TEAMS_INFO);
    lldpIntent.putExtra("CHASSIS_ID", chassisID);
    lldpIntent.putExtra("CHASSIS_SUB_TYPE", lldpChassisSubType);
    lldpIntent.putExtra("PORT_SUB_TYPE", lldpPortSubType);
    lldpIntent.putExtra("PORT_ID", portID);
    lldpIntent.putExtra("CORRELATION_ID", correlationIDUpCassStr);
    lldpIntent.addFlags(0x01000000);
    mContext.sendBroadcastAsUser(lldpIntent, UserHandle.ALL);

七、lldpcli常用指令

1、查看周围的邻居列表

root@hbg:/# lldpcli show neighbors
-------------------------------------------------------------------------------
LLDP neighbors:
-------------------------------------------------------------------------------
Interface:    eth0, via: LLDP, RID: 1, Time: 0 day, 00:07:15
Chassis:    
ChassisID:    mac 99:11:99:33:00:85
SysName:     hbg
SysDescr:     OpenWrt Barrier Breaker 14.07 @ hbg
Capability:   Bridge, on
Capability:   Router, on
Capability:   Wlan, on
Port:       
PortID:       mac 99:11:99:33:00:85
PortDescr:    eth0
-------------------------------------------------------------------------------

2、查看lldp的统计信息

ribeye:/data/data/lldpd # lldpcli show stat
-------------------------------------------------------------------------------
LLDP statistics:
-------------------------------------------------------------------------------
Interface:    dummy0
  Transmitted:  47
  Received:     0
  Discarded:    0
  Unrecognized: 0
  Ageout:       0
  Inserted:     0
  Deleted:      0
-------------------------------------------------------------------------------
Interface:    eth0
  Transmitted:  0
  Received:     0
  Discarded:    0
  Unrecognized: 0
  Ageout:       0
  Inserted:     0
  Deleted:      0
-------------------------------------------------------------------------------
Interface:    wlan0
  Transmitted:  47
  Received:     0
  Discarded:    0
  Unrecognized: 0
  Ageout:       0
  Inserted:     0
  Deleted:      0
-------------------------------------------------------------------------------

或者使用命令 lldpcli show statistics
3、查看当前的配置信息

ribeye:/data/data/lldpd # lldpcli show configuration
-------------------------------------------------------------------------------
Global configuration:
-------------------------------------------------------------------------------
Configuration:
  Transmit delay: 30
  Transmit delay in milliseconds: 30000
  Transmit hold: 4
  Maximum number of neighbors: 32
  Receive mode: no
  Pattern for management addresses: (none)
  Interface pattern: (none)
  Permanent interface pattern: (none)
  Interface pattern for chassis ID: (none)
  Override chassis ID with: (none)
  Override description with: (none)
  Override platform with: Linux
  Override system name with: (none)
  Advertise version: yes
  Update interface descriptions: no
  Promiscuous mode on managed interfaces: no
  Disable LLDP-MED inventory: yes
  LLDP-MED fast start mechanism: yes
  LLDP-MED fast start interval: 1
  Source MAC for LLDP frames on bond slaves: local
  Port ID TLV subtype for LLDP frames: unknown
  Agent type:   unknown
-------------------------------------------------------------------------------

或者使用命令** lldpcli show running-configuration**
4、 查看interface的信息
lldpcli show interface

1|ribeye:/data/data/lldpd # lldpcli show interface
-------------------------------------------------------------------------------
LLDP interfaces:
-------------------------------------------------------------------------------
Interface:    dummy0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac 1e:cc:82:42:f4:48
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #4 SMP PREEMPT Tue Aug 16 13:06:38 CST 2022 armv8l
    MgmtIP:       192.168.200.199
    MgmtIface:    9
    MgmtIP:       fe80::1ccc:82ff:fe42:f448
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 1e:cc:82:42:f4:48
    PortDescr:    dummy0
  TTL:          120
-------------------------------------------------------------------------------
Interface:    eth0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac 1e:cc:82:42:f4:48
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #4 SMP PREEMPT Tue Aug 16 13:06:38 CST 2022 armv8l
    MgmtIP:       192.168.200.199
    MgmtIface:    9
    MgmtIP:       fe80::1ccc:82ff:fe42:f448
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 50:de:19:e0:c3:c7
    PortDescr:    eth0
  TTL:          120
-------------------------------------------------------------------------------
Interface:    wlan0
  Administrative status: RX and TX
  Chassis:
    ChassisID:    mac 1e:cc:82:42:f4:48
    SysName:      localhost
    SysDescr:      Linux 5.10.66 #4 SMP PREEMPT Tue Aug 16 13:06:38 CST 2022 armv8l
    MgmtIP:       192.168.200.199
    MgmtIface:    9
    MgmtIP:       fe80::1ccc:82ff:fe42:f448
    MgmtIface:    2
    Capability:   Bridge, off
    Capability:   Router, off
    Capability:   Wlan, on
    Capability:   Station, off
  Port:
    PortID:       mac 08:fb:ea:ff:bd:72
    PortDescr:    wlan0
  TTL:          120
-------------------------------------------------------------------------------

image.png

猜你喜欢

转载自blog.csdn.net/franc521/article/details/130134816
今日推荐