br-lan: received packet on eth2.1 with own address as source address

本文介绍了解决OpenWRT路由器中因LAN-WAN共用同一物理网卡导致的告警问题。通过分析发现告警源于MAC地址冲突,并给出了通过修改LAN/WAN的MAC地址解决问题的方法。

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27057175&id=4740299

路由器是OpenWRT系统的,接上网络后,一直出现这句告警,

但是不影响连通性。

首先看到这个是内核打印的,查了其他人的解释,
1. brctl stp intf on
2. 关闭ipv6
都试过了,无效!
进入了一个误区,因为是br-lan一直打印这个,导致认为lan配置有问题。

偶然把wan口连接断开,告警消失了?
这才想到,我的路由器lan wan实际上同一个eth物理网卡,只是虚拟出来的vlan,MAC地址也就是相同的。为了方便,我把lan wan都通过同一个交换机接到PC,wan口寻找自己的gateway和DNS,向外狂发广播包,到了交换机,包就又回到了路由器的lan口。这样收到的报文srcmac和br-lan口自己mac相同了,故而有这个告警!!!!!
原来这个告警的address是MAC address。
愚蠢的错误

查看内核源码,这个告警只在bridge模块(net/bridge/br_fdb.c)才会检查,不在lan上创建bridge则没有问题
把lan/wan的hwaddr用ifconfig修改成不一样的,就可以彻底解决。
目的 ESP32除了可以使用无线网络外还可以通过外接PHY模块来使用有线网络(Ethernet:以太网),本篇将介绍相关内容。 基本说明 本篇中使用常用的PHY芯片LAN8720的模块来来进行有线网络使用演示。 接线定义 下面是ESP32LAN8720间RMII PHY的连接定义,用于以太网通信,下面几个针脚必须按定义连接: GPIO RMII Signal ESP32 EMAC Function Notes GPIO21 TX_EN EMAC_TX_EN GPIO19 TX0 EMAC_TXD0 GPIO22 TX1 EMAC_TXD1 GPIO25 RX0 EMAC_RXD0 GPIO26 RX1 EMAC_RXD1 GPIO27 CRS_DV EMAC_RX_DRV 下面是ESP32LAN8720间RMII PHY SMI的连接定义,用于ESP32读写LAN8720的寄存器,下面的针脚理论上可以连接到ESP32任何支持输出的针脚上: Default Example GPIO RMII Signal Notes1 Notes2 GPIO23 MDC 输出至LAN8720 也可以使用ESP32其他输出脚 GPIO18 MDIO 双向通讯 也可以使用ESP32其他双向脚 使用步骤 引用以太网库#include <ETH.h>; 声明一个对象ETHClass myETH,默认的已经声明了一个名为ETH的对象; 使用begin()方法启动以太网连接; 常用方法说明 bool begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type, eth_clock_mode_t clock_mode) 启用以太网连接,参数说明如下: phy_addr:LAN8720写0或1、TLK110写31; power:设置ESP32某管脚,该管脚可以用来管理LAN8720供电,使能时输出高电平,失能时为低电平,写-1则不使用; mdc:mdc管脚编号,写-1则不使用; mdio:mdio管脚编号,写-1则不使用; type:PHY类型,ETH_PHY_LAN8720或ETH_PHY_TLK110; clock_mode:时钟模式,可选值ETH_CLOCK_GPIO0_IN、ETH_CLOCK_GPIO0_OUT、ETH_CLOCK_GPIO16_OUT、ETH_CLOCK_GPIO17_OUT,详细介绍见后文; bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000) 设置IP地址、网关地址、子网掩码、dns地址; const char * getHostname() 获取主机名字; bool setHostname(const char * hostname) 设置主机名字; bool fullDuplex() 检查是否为全双工通讯; uint8_t linkSpeed() 获取传输速度,单位Mbps; IPAddress localIP() 获取IP地址; IPAddress subnetMask() 获取子网掩码; IPAddress gatewayIP() 获取网关地址; IPAddress dnsIP(uint8_t dns_no = 0) 获取dns服务器地址; String macAddress() 获取mac地址; 使用演示 数据通讯 使用下面代码进行以太网通讯演示: #include <ETH.h> //引用以使用ETH #include <WiFiUdp.h> #define ETH_ADDR 1 #define ETH_POWER_PIN -1 #define ETH_MDC_PIN 23 #define ETH_MDIO_PIN 18 #define ETH_TYPE ETH_PHY_LAN8720 #define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT WiFiUDP Udp; //创建UDP对象 unsigned int localUdpPort = 2333; //本地端口号 void setup() { Serial.begin(115200); Serial.println(); ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); //启用ETH while(!((uint32_t)ETH.localIP())) //等待获取到IP { } Serial.println("Connected"); Serial.print("IP Address:"); Serial.println(ETH.localIP()); Udp.begin(localUdpPort); //启用UDP监听以接收数据 } void loop() { int packetSize = Udp.parsePacket(); //获取当前队首数据包长度 if (packetSize) //如果有数据可用 { char buf[packetSize]; Udp.read(buf, packetSize); //读取当前包数据 Serial.println(); Serial.print("Received: "); Serial.println(buf); Serial.print("From IP: "); Serial.println(Udp.remoteIP()); Serial.print("From Port: "); Serial.println(Udp.remotePort()); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //准备发送数据 Udp.print("Received: "); //复制数据到发送缓存 Udp.write((const uint8_t*)buf, packetSize); //复制数据到发送缓存 Udp.endPacket(); //发送数据 } } AI写代码 c 运行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 上面例子中启用以太网等待获取到IP,然后用UDP进行了通讯测试; 事件响应 使用下面代码进行以太网事件演示: #include <ETH.h> //引用以使用ETH #define ETH_ADDR 1 #define ETH_POWER_PIN -1 #define ETH_MDC_PIN 23 #define ETH_MDIO_PIN 18 #define ETH_TYPE ETH_PHY_LAN8720 #define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT void printETHInfo(void) //打印基本信息 { Serial.print("ETH MAC: "); Serial.print(ETH.macAddress()); Serial.print(", IPv4: "); Serial.print(ETH.localIP()); if (ETH.fullDuplex()) { Serial.print(", FULL_DUPLEX"); } Serial.print(", "); Serial.print(ETH.linkSpeed()); Serial.println("Mbps"); } void WiFiEvent(WiFiEvent_t event) { switch (event) { case SYSTEM_EVENT_ETH_START: //启动ETH成功 Serial.println("ETH Started"); break; case SYSTEM_EVENT_ETH_CONNECTED: //接入网络 Serial.println("ETH Connected"); break; case SYSTEM_EVENT_ETH_GOT_IP: //获得IP Serial.println("ETH GOT IP"); printETHInfo(); break; case SYSTEM_EVENT_ETH_DISCONNECTED: //失去连接 Serial.println("ETH Disconnected"); break; case SYSTEM_EVENT_ETH_STOP: //关闭 Serial.println("ETH Stopped"); break; default: break; } } void setup() { Serial.begin(115200); Serial.println(); WiFi.onEvent(WiFiEvent); //注册事件 ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); //启用ETH } void loop() { delay(10000); esp_eth_disable(); //关闭eth } AI写代码 c 运行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 上面演示时在获取到IP地址后我将网线拔了,手动触发了SYSTEM_EVENT_ETH_DISCONNECTED事件; 有事件的话其实上个例子中while(!((uint32_t)ETH.localIP())){} //等待获取到IP这句就可以用事件来处理了; 其他说明 PHY地址 PHY地址LAN8720写0或1、TLK110写31LAN8720使用0还是1由芯片复位时RXER引脚电平决定,当该引脚接下拉电阻或者浮空(芯片内部下拉)时,地址就为0,当引脚接上拉电阻时地址为1; 上文使用的模块电路中RXER脚外接了上拉电阻,所以地址写1; 时钟 理论上LAN8720和ESP32需要有同一个时钟源用于以太网通讯,ESP32提供了四种方式来处理时钟: Mode GPIO Pin Signal name Notes external GPIO0 EMAC_TX_CLK Input of 50MHz PHY clock internal GPIO0 CLK_OUT1 Output of 50MHz APLL clock. Signal quality might be an issue. internal GPIO16 EMAC_CLK_OUT Output of 50MHz APLL clock. internal GPIO17 EMAC_CLK_180 Inverted output of 50MHz APLL clock. Found to be best suitable for LAN8720 with long signal lines. 第一种方式是外部输入,LAN8720和ESP32接入同一个外部50Mhz时钟; 第二种方式由ESP32(GPIO0)提供时钟给LAN8720,信号质量可能不怎么样; 第三种方式由ESP32(GPIO16)提供时钟给LAN8720; 第四种方式由ESP32(GPIO17)提供时钟给LAN8720,最合适用于LAN8720; 上文使用的模块并没有引出时钟到外部针脚,也没法选择使用时钟来源,所以上面使用时相当于LAN8720使用了模块自带的时钟,而ESP32虽然设置为时钟输出模式,但其实没有真正输出给LAN8720,这种情况下虽然能够正常通讯,但是不是那么符合理论设计,有一定概率会导致通讯失败。(可以把模块上的晶振拆了,然后用飞线连接ESP32 GPIO17和LAN8720模块晶振时钟输出脚,可以大大提升通讯稳定性) 另外如果使用外部时钟连接到GPIO0时还需要特别注意电路设计: Because GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when also using this pin as EMAC_TX_CLK. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. One solution is to use an additional GPIO as a “power pin”, which either powers the PHY on/off or enables/disables the PHY’s own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, GPIO0 also needs a pullup resistor and the “power pin” GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. 通讯应用 除UDP外,Ethernet也可以使用WiFiClient和WiFiServer等通讯功能
最新发布
08-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值