一、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命令发送广播。
需要注意的有以下几点:
- 写的sh脚本必须在Linux环境下,或者类似于cygwin这样的Linux唤醒,否则即使在简单的指令也有可能由于格式问题执行失败;
- 我们的写的native服务如果需要常驻,即作为守护进程,需要在服务起来后,做一个死循环,在循环里面做该做的事情,否则代理服务退出后,该服务也将被退出;如果native服务不是我们自己写的,可以通过起脚本,脚本在最后启动完服务后,sleep xxxxxx 防止服务退出;
- 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
-------------------------------------------------------------------------------
从以上测试得出以下结论:
- 连接不同SSID,LLDP中ChassisID和PortID不变
- 回厂后连接相同SSID,ChassisID改变,PortID不变,也就是说回厂后ChassisID会发生变化
- 重启后连接相同SSID,ChassisID改变,PortID不变,也就是说回厂后ChassisID会发生变化
- 切换到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
-------------------------------------------------------------------------------