高效小工具 | 将网卡的mac地址刷写进eeprom

3,980 阅读2分钟

前言

相信很多jy都对ethtool这个工具不陌生。那为什么还要再写一个将mac地址刷写进eeprom的小工具呢?因为并不是所有设备都能适配这些通用工具,工具也是要为具体的需求服务的。

工具实现愿景

基础版:命令行模式

以下为工具的可选参数(mac地址为必填项),如未指定则使用默认从参数

-b, --bus I2C总线 
-a, --addr 外设地址 
-o, --offset 偏移后的起始位置
-m, --mac 首个MAC地址,支持两种形式的输入,形如: `1a2b3c112233` or `1a:2b:3c:11:22:33`) 
-c, --count MAC地址个数,每写一个MAC地址自增1 
-i, --interval 两个MAC地址的间隔,默认0 
-h, --help 打印上述选项

进阶版

增加可视化的交互界面

实现思路

刷写原理

这个问题的实质是:利用什么协议来进行数据传输? 在一些很简单的硬件设备中,不支持高级协议,所以在之前的文章中介绍过的、只需要两根线(如果加上地线就是三根)的i2c协议是一个不错的选择。

在本项目中可以用<linux/i2c.h><linux/i2c-dev.h>这两个i2c开源库。

各环节的具体实现方案

从全流程来看:

  • 数据输入:命令行参数可使用getopt这个库来接收。
//全局变量定义
static const struct option longopts[] = {
	{"bus", required_argument, NULL, 'b'},
	{"addr", required_argument, NULL, 'a'},
	{"offset", required_argument, NULL, 'o'},
	{"mac", required_argument, NULL, 'm'},
	{"count", required_argument, NULL, 'c'},
	{"interval", required_argument, NULL, 'i'},
	{"help", no_argument, NULL, 'h'},
	{GETOPT_NULL_LONGOPT},
};

static const char *const shortopts = "+b:a:o:m:c:i:h";

//main函数中
int optc, opti;
	for (;;)
	{
		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
		if (optc < 0)
			break;

		switch (optc)
		{
		case 'b':
			setBus(optarg);
			break;
		case 'a':
			setPaddr(optarg);
			break;
		case 'o':
			setOffset(optarg);
			break;
		case 'm':
			setMacaddr(optarg);
			break;
		case 'c':
			setMaccnt(optarg);
			break;
		case 'i':
			setIndex(optarg);
			break;
		case 'h':
			print_help();
			return 0;
		default:
			abort();
		}
	}
  • 数据校验:在本项目中,要对参数进行合法性校验,比如输入的mac地址需符合规定格式,这可以用正则表达式来辅助判断
	regex pattern("(^[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}$)");
	string str = option;
	std::regex e(":");
	smatch result;
	bool ret = regex_match(str, result, pattern);
	if (!ret)
		cout << "mac address format error!";
  • 算法核心:这是项目的核心逻辑,要完成的任务包括但不限于:接收参数后对相关属性进行赋值(要先进行数据清洗和转换)、调用并封装i2c库进行数据刷写、编写代码使得对底层寄存器的数值写入符合项目要求等等。

由于某些原因,这里不方便展示核心代码,对这方面感兴趣的uu可以自行上网搜索i2c库的相关调用代码并且将它修改为合适项目需求的样子。

大家只需要记住一点:

刷写的本质就是往寄存器写数据。

这一点想通之后再抽象的需求也会变得明朗。

界面(可选)

为了更好地适配不同的操作系统,小工具不采用web端或者高级桌面应用框架进行开发,而是采用基于命令行的工具whiptail

它的开发过程很简单。这个只是一个界面,作用是接收参数并传入真正的可执行程序。 以下以本程序的必选参数macaddr为例,读者可以自行添加其他选项的输入页面、增加用户欢迎页等等,参考文档详见参考资料[2]

macaddr=$(whiptail --inputbox "首个MAC地址" 10 60 1a2b3c112233 3>&1 1>&2 2>&3)
./mac -m $macaddr

参考资料