AutoIP 的嵌入式应用

背景

开发的产品需要增加 AutoIP 功能,具体要求如下:

  1. 当设置为 DHCP 时,如果 DHCP 获取或续约失败,则启用 AutoIP 获取 IP 地址

  2. AutoIP 期间,DHCP 一旦成功则切换到 DHCP 获得的 IP 地址

介绍 Zeroconf

Zeroconf 全称为 Zero configuration networking,提出者是 Apple 公司,中文名则为零配置网络规范,是一种用于自动生成可用 IP 地址的网络技术,不需要额外的手动配置和专属的配置服务器

“零配置网络服务”的目标,是让非专业用户也能便捷的连接各种网络设备,例如计算机、打印机等。整个搭建网络的过程都是通过程序自动化完成
如果没有 Zeroconf,用户必须手动配置一些服务,例如 DHCP、DNS、计算机网络的其它设置等。这些对非技术用户和新用户们来说是很难的事情

很多 Linux 发行版都默认安装该服务,当系统无法连接 DHCP server 的时候,就会尝试通过 Zeroconf 来获取 IP

举个例子:
用户拥有一台 Apple TV 和一台 iPhone X,它们只要都连入到同一个无线局域网内,iPhone X 就会自动找出 Apple TV,那么在播放音乐或者视频的时候,用户只要点击推送,就可以将音乐和视频推送到 Apple TV 上播放

Zeroconf 既然是协议,因此对应的是各种产品的实现,现在最主要的实现是 Apple 公司的 Bonjour 和开源的 Avahi

介绍 Avahi

Avahi 是 Zeroconf 规范的开源实现,基本是使用在 Linux 和 FreeBSD 上。包含了一整套多播 DNS(multicast DNS)/DNS-SD 网络服务的实现,使用的发布授权是 LGPL。在程序接口上,它使用 DNSD 与 Apple 的 Bonjour 进行兼容,方便原来使用 Bonjour 的产品进行迁移
目前在绝大多数的 Linux 发行版本中,都将 Avahi 作为系统启动进程,并且大量的服务也依赖于avahi
Avahi 也是用纯 C 编写的,同样也可以使用诸如 Java 语言去调用

Avahi 允许程序在不需要进行手动配置网络的情况下,在一个本地网络中发布和获知各种服务和主机。例如,当某用户把他的计算机接入到某个局域网时,如果他的计算机运行有 Avahi 服务,则 Avahi 程序就会自动广播,从而发现网络中可用的打印机、共享文件和可相互聊天的其他用户

接下来介绍在嵌入式怎么使用 Avahi …

软件包

下载所需的软件包,avahi 需要依赖:

  1. expat,用于解析 XML 文件的 ( --with-xml=expat )
  2. libdaemon,编译 avahi 必须的包,用于支持 avahi-daemon ( --enable-libdaemon )

http://distfiles.macports.org/expat/expat-2.1.0.tar.gz
http://distfiles.macports.org/libdaemon/libdaemon-0.14.tar.gz
http://distfiles.macports.org/avahi/avahi-0.6.31.tar.gz

例如,按照下图的文件组织结构摆放好,编译生成的头文件和库文件设定存放在 out 目录
在这里插入图片描述

交叉编译

先来看 expat,Makefile 如下,配置自己的交叉工具链,没什么需要特别注意的

export CROSS_COMPILE ?= arm-linux-
export CC      := $(CROSS_COMPILE)gcc
export CXX     := $(CROSS_COMPILE)g++
export AR      := $(CROSS_COMPILE)ar
export RANLIB  := $(CROSS_COMPILE)ranlib
export LD      := $(CROSS_COMPILE)ld
export STRIP   := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = expat-2.1.0
PREFIX_DIR = $(shell pwd)/../out
default: clean
	make install
clean:
	rm -rf $(NAME)
unpack: clean
	tar xzvf $(NAME).tar.gz
config: unpack
	cd $(NAME) && ./configure\
		--host=arm-linux\
		--build=i686-linux\
		--prefix=$(PREFIX_DIR)
build: config
	make -C $(NAME)
install: build
	make -C $(NAME) install

其次是 libdaemon

export CROSS_COMPILE ?= arm-linux-
export CC      := $(CROSS_COMPILE)gcc
export CXX     := $(CROSS_COMPILE)g++
export AR      := $(CROSS_COMPILE)ar
export RANLIB  := $(CROSS_COMPILE)ranlib
export LD      := $(CROSS_COMPILE)ld
export STRIP   := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = libdaemon-0.14
PREFIX_DIR = $(shell pwd)/../out
default: clean
	make install
clean:
	rm -rf $(NAME)
unpack: clean
	tar xzvf $(NAME).tar.gz
config: unpack
	echo "ac_cv_func_setpgrp_void=yes" > $(NAME)/config.cache
	cd $(NAME) && ./configure\
		--host=arm-linux\
		--build=i686-linux\
		--config-cache\
		--prefix=$(PREFIX_DIR)\
		--disable-lynx
build: config
	make -C $(NAME)
install: build
	make -C $(NAME) install

再到 avahi,需要注意的是第 49 行,要加上prefix=""才行,否则运行不起来
运行 avahi 进程的时候,需要一个配置文件叫 avahi-autoipd.action
prefix=""表示配置文件的路径是在 /etc/avahi/avahi-autoipd.action

export CROSS_COMPILE ?= arm-linux-
export CC      := $(CROSS_COMPILE)gcc
export CXX     := $(CROSS_COMPILE)g++
export AR      := $(CROSS_COMPILE)ar
export RANLIB  := $(CROSS_COMPILE)ranlib
export LD      := $(CROSS_COMPILE)ld
export STRIP   := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = avahi-0.6.31
PREFIX_DIR = $(shell pwd)/../out
default: clean
	make install
clean:
	rm -rf $(NAME)
unpack:
	tar xzvf $(NAME).tar.gz
config: unpack
	cd $(NAME) && ./configure\
		--host=arm-linux\
		--build=i686-linux\
		--prefix=$(PREFIX_DIR)\
		--disable-dbus\
		--disable-gdbm\
		--disable-glib\
		--disable-gobject\
		--disable-gtk\
		--disable-gtk3\
		--disable-manpages\
		--disable-monodoc\
		--disable-python\
		--disable-qt3\
		--disable-qt4\
		--enable-libdaemon\
		--with-distro=none\
		--with-xml=expat\
		--with-avahi-user=root\
		--with-avahi-group=root\
		--with-autoipd-user=root\
		--with-autoipd-group=root\
		CC=$(CC)\
		CXX=$(CXX)\
		LD=$(LD)\
		RANLIB=$(RANLIB)\
		CFLAGS="-I$(PREFIX_DIR)/include"\
		CXXFLAGS="-I$(PREFIX_DIR)/include"\
		LDFLAGS="-L$(PREFIX_DIR)/lib"\
		PKG_CONFIG_PATH="$(PREFIX_DIR)/lib/pkgconfig"
build: config
	make -C $(NAME) prefix=""
install: build
	make -C $(NAME) install

最后到最外层的 Makefile,统揽全局,只需在最外层敲一个make就可以编译完

PREFIX_DIR = $(shell pwd)/out
default: clean
	test -z $(PREFIX_DIR) || mkdir -p $(PREFIX_DIR)
	make -C expat
	make -C libdaemon
	make -C avahi
clean:
	make -C expat clean
	make -C libdaemon clean
	make -C avahi clean

准备环境

一块开发板、一个交换机、一个路由器,按下图连接好
在这里插入图片描述

为了能快速验证 autoip 的功能,我们把路由器的 DHCP 租约时间设置为最小,本实验所用路由器最小租约时间是 2 分钟
正常的时候,PC 和开发板都是可以上外网的,当然也可以互相 ping 通

正常时 PC 的 IP 信息如下
在这里插入图片描述

正常时开发板的 IP 信息如下
在这里插入图片描述

实验

把 out/lib 目录的动态库文件拷贝到开发板的 /lib 目录
在这里插入图片描述

把 out/sbin 目录的可执行文件拷贝到开发板的 /sbin 目录
在这里插入图片描述

在开发板运行avahi-autoipd -h查看帮助文档可知,需要一个脚本
在这里插入图片描述

把 out/etc/avahi 目录的配置文件 avahi-autoipd.action 拷贝到开发板的 /etc/avahi 目录

运行 avahi-autoipd,命令是:
/sbin/avahi-autoipd -D eth0 --script=/etc/avahi/avahi-autoipd.action

这时候,拔掉上面连接图的红色这根网线,然后等待 2 分钟左右,开发板会去请求 DHCP 续租,但是网线已被我们拔掉,请求已经达到不了路由器这边了,所以这时候 autoip 会自动获取一个 169.254.xxx.xxx 的地址,ifconfig 看到的地址信息如下图
在这里插入图片描述

再看 PC 这边的地址信息,因为 PC 本身就内置了 Zeroconf 协议的实现,所以 PC 也会拿到一个 169.254.xxx.xxx 的地址,如下图
在这里插入图片描述

此时,PC 和 开发板之间依然可以进行通信,因为他们还在一个局域网里头

参考资料

https://www.xuebuyuan.com/3195396.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章