前景描述

我司的以太网实现是LAN8720搭配片上MAC层做的,协议栈用LWIP

这种做法应该还是蛮常见的,反正不是LAN8720就是DP83864,再不然就是硬件协议栈的W5500了

想想还是有MAC层过滤比较好,随手翻了翻它的手册,W5500好像是没得MAC层过滤的

假如数据速率比较高,数据量大,而且外面还有乱七八糟无关的数据往板卡送,我也不知道用这个片子到底好不好

LAN8720也不好改了,就继续用吧

好好在,发给板卡的数据的MAC还是有特征的,我只需要过滤发送方MAC地址的前3个字节,也就是特定的厂家那段

MAC地址的科普知识这里就不过多描述了,我们直奔主题

怎么用STM32 F7的片上MAC做MAC层过滤

写这个的目的,就是我搜了搜,没看见有人写这个MAC层过滤功能,具体代码怎么写才能用

知识科普-STM32的片上MAC

STM32 F7的MAC层过滤方式有三种(说人话的直白解释,中文手册其实也翻译的不好)

  1. 精确过滤(手册上叫单播目标/源地址过滤)

  2. 粗糙过滤(手册上叫Hash表过滤)

  3. 特殊过滤(广播,组播过滤等等特殊的过滤)

我这里着重说第1种和第3种

STM32 F7可以存4个MAC地址

其中MAC地址0是自己的MAC,其他三个可以用来做过滤

网络数据包通过PHY进入STM32的MAC,MAC层是可以对目的地址/源地址检查并过滤掉没得用的数据的,默认的HAL库库函数HAL_ETH_Init中

有一个static的函数

static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)

会帮你在初始化网络功能时初始化默认的MAC层功能:

  1. 关闭源地址过滤

  2. 不接收所有数据

  3. 接收广播帧

  4. 打开目的地地址过滤

  5. 单播数据精确过滤

  6. 组播数据精确过滤

  7. Hash表过滤关闭

其他的功能自行研究,我这里捡重要的说

static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
{ETH_MACInitTypeDef macinit;ETH_DMAInitTypeDef dmainit;uint32_t tmpreg = 0;if (err != ETH_SUCCESS) /* Auto-negotiation failed */{/* Set Ethernet duplex mode to Full-duplex */(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;/* Set Ethernet speed to 100M */(heth->Init).Speed = ETH_SPEED_100M;}/* Ethernet MAC default initialization **************************************/macinit.Watchdog = ETH_WATCHDOG_ENABLE;macinit.Jabber = ETH_JABBER_ENABLE;macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;if(heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE){macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;}else{macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;}
//这一段是MAC层过滤的设置,下面是DMA的,那个用默认的就可以macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE;macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;macinit.HashTableHigh = 0x0;macinit.HashTableLow = 0x0;macinit.PauseTime = 0x0;macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;macinit.VLANTagIdentifier = 0x0;/*------------------------ ETHERNET MACCR Configuration --------------------*//* Get the ETHERNET MACCR value */tmpreg = (heth->Instance)->MACCR;/* Clear WD, PCE, PS, TE and RE bits */tmpreg &= ETH_MACCR_CLEAR_MASK;/* Set the WD bit according to ETH Watchdog value *//* Set the JD: bit according to ETH Jabber value *//* Set the IFG bit according to ETH InterFrameGap value *//* Set the DCRS bit according to ETH CarrierSense value *//* Set the FES bit according to ETH Speed value *//* Set the DO bit according to ETH ReceiveOwn value *//* Set the LM bit according to ETH LoopbackMode value *//* Set the DM bit according to ETH Mode value *//* Set the IPCO bit according to ETH ChecksumOffload value *//* Set the DR bit according to ETH RetryTransmission value *//* Set the ACS bit according to ETH AutomaticPadCRCStrip value *//* Set the BL bit according to ETH BackOffLimit value *//* Set the DC bit according to ETH DeferralCheck value */tmpreg |= (uint32_t)(macinit.Watchdog |macinit.Jabber |macinit.InterFrameGap |macinit.CarrierSense |(heth->Init).Speed |macinit.ReceiveOwn |macinit.LoopbackMode |(heth->Init).DuplexMode |macinit.ChecksumOffload |macinit.RetryTransmission |macinit.AutomaticPadCRCStrip |macinit.BackOffLimit |macinit.DeferralCheck);/* Write to ETHERNET MACCR */(heth->Instance)->MACCR = (uint32_t)tmpreg;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->MACCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACCR = tmpreg;/*----------------------- ETHERNET MACFFR Configuration --------------------*//* Set the RA bit according to ETH ReceiveAll value *//* Set the SAF and SAIF bits according to ETH SourceAddrFilter value *//* Set the PCF bit according to ETH PassControlFrames value *//* Set the DBF bit according to ETH BroadcastFramesReception value *//* Set the DAIF bit according to ETH DestinationAddrFilter value *//* Set the PR bit according to ETH PromiscuousMode value *//* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value *//* Set the HUC and HPF bits according to ETH UnicastFramesFilter value *//* Write to ETHERNET MACFFR */(heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |macinit.SourceAddrFilter |macinit.PassControlFrames |macinit.BroadcastFramesReception |macinit.DestinationAddrFilter |macinit.PromiscuousMode |macinit.MulticastFramesFilter |macinit.UnicastFramesFilter);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->MACFFR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFFR = tmpreg;/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*//* Write to ETHERNET MACHTHR */(heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;/* Write to ETHERNET MACHTLR */(heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;/*----------------------- ETHERNET MACFCR Configuration -------------------*//* Get the ETHERNET MACFCR value */tmpreg = (heth->Instance)->MACFCR;/* Clear xx bits */tmpreg &= ETH_MACFCR_CLEAR_MASK;/* Set the PT bit according to ETH PauseTime value *//* Set the DZPQ bit according to ETH ZeroQuantaPause value *//* Set the PLT bit according to ETH PauseLowThreshold value *//* Set the UP bit according to ETH UnicastPauseFrameDetect value *//* Set the RFE bit according to ETH ReceiveFlowControl value *//* Set the TFE bit according to ETH TransmitFlowControl value */tmpreg |= (uint32_t)((macinit.PauseTime << 16) |macinit.ZeroQuantaPause |macinit.PauseLowThreshold |macinit.UnicastPauseFrameDetect |macinit.ReceiveFlowControl |macinit.TransmitFlowControl);/* Write to ETHERNET MACFCR */(heth->Instance)->MACFCR = (uint32_t)tmpreg;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->MACFCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFCR = tmpreg;/*----------------------- ETHERNET MACVLANTR Configuration ----------------*//* Set the ETV bit according to ETH VLANTagComparison value *//* Set the VL bit according to ETH VLANTagIdentifier value */(heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |macinit.VLANTagIdentifier);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->MACVLANTR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACVLANTR = tmpreg;/* Ethernet DMA default initialization ************************************/dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;dmainit.DescriptorSkipLength = 0x0;dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;/* Get the ETHERNET DMAOMR value */tmpreg = (heth->Instance)->DMAOMR;/* Clear xx bits */tmpreg &= ETH_DMAOMR_CLEAR_MASK;/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value *//* Set the RSF bit according to ETH ReceiveStoreForward value *//* Set the DFF bit according to ETH FlushReceivedFrame value *//* Set the TSF bit according to ETH TransmitStoreForward value *//* Set the TTC bit according to ETH TransmitThresholdControl value *//* Set the FEF bit according to ETH ForwardErrorFrames value *//* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value *//* Set the RTC bit according to ETH ReceiveThresholdControl value *//* Set the OSF bit according to ETH SecondFrameOperate value */tmpreg |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |dmainit.ReceiveStoreForward |dmainit.FlushReceivedFrame |dmainit.TransmitStoreForward |dmainit.TransmitThresholdControl |dmainit.ForwardErrorFrames |dmainit.ForwardUndersizedGoodFrames |dmainit.ReceiveThresholdControl |dmainit.SecondFrameOperate);/* Write to ETHERNET DMAOMR */(heth->Instance)->DMAOMR = (uint32_t)tmpreg;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->DMAOMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMAOMR = tmpreg;/*----------------------- ETHERNET DMABMR Configuration ------------------*//* Set the AAL bit according to ETH AddressAlignedBeats value *//* Set the FB bit according to ETH FixedBurst value *//* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value *//* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value *//* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*//* Set the DSL bit according to ETH DesciptorSkipLength value *//* Set the PR and DA bits according to ETH DMAArbitration value */(heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |dmainit.FixedBurst |dmainit.RxDMABurstLength |    /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */dmainit.TxDMABurstLength |dmainit.EnhancedDescriptorFormat |(dmainit.DescriptorSkipLength << 2) |dmainit.DMAArbitration |ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx *//* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg = (heth->Instance)->DMABMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMABMR = tmpreg;if((heth->Init).RxMode == ETH_RXINTERRUPT_MODE){/* Enable the Ethernet Rx Interrupt */__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);}/* Initialize MAC address in ethernet MAC */ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
}

这里我就要稍微吐槽一下HAL库了

MAC层过滤的设置没有预留接口出来,有设置MAC地址的函数

static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)

就不多做一个设置MAC层过滤的函数嘛,连后面用到的宏定义都有~~

木有办法,自己编一个初始化MAC层过滤的函数吧

其实也就是把上面这个ETH_MACDMAConfig函数分离成两个单独的设置函数,再编一个设置MAC层过滤的函数

开启MAC层过滤的初始化代码

uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth)
{ETH_MACInitTypeDef macinit;/* Ethernet MAC default initialization **************************************/macinit.Watchdog = ETH_WATCHDOG_ENABLE;macinit.Jabber = ETH_JABBER_ENABLE;macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE){macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;}else{macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;}macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE;    //使能重传macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE;      //使能自动去除macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; //多播过滤macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; //单播过滤macinit.HashTableHigh = 0x0; //Hash表高位macinit.HashTableLow = 0x0; //Hash表低位macinit.PauseTime = 0x0;macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;macinit.VLANTagIdentifier = 0x0;return HAL_ETH_ConfigMAC(heth, &macinit);
}

默认的MAC层 DMA初始化函数

uint8_t ETH_DMA_Setting(ETH_HandleTypeDef *heth)
{ETH_DMAInitTypeDef dmainit;/* Ethernet DMA default initialization ************************************/dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;dmainit.DescriptorSkipLength = 0x0;dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;uint8_t res =  HAL_ETH_ConfigDMA(heth, &dmainit);if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE){/* Enable the Ethernet Rx Interrupt */__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);}return res;
}

用来设置MAC地址的函数(其实就是把库函数的static函数取出来直接用了)

//heth: HAL句柄
//MacAddr:哪个MAC地址(ETH_MAC_ADDRESS0-3)
//Addr: MAC地址的uint8_t数组
static void ETH_MAC_ADDR_Config(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)
{uint32_t tmpreg;/* Check the parameters */assert_param(IS_ETH_MAC_ADDRESS0123(MacAddr));/* Calculate the selected MAC address high register */tmpreg = ((uint32_t) Addr[5] << 8) | (uint32_t) Addr[4];/* Load the selected MAC address high register */(*(__IO uint32_t *) ((uint32_t) (ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg;/* Calculate the selected MAC address low register */tmpreg = ((uint32_t) Addr[3] << 24) | ((uint32_t) Addr[2] << 16) | ((uint32_t) Addr[1] << 8) | Addr[0];/* Load the selected MAC address low register */(*(__IO uint32_t *) ((uint32_t) (ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg;
}

然后到最最重要的MAC层过滤设置

以MAC1为例

注意看红框的描述

功能很好用,可以过滤源地址/目的地址,还可以做掩码功能

设置MAC层过滤的代码

static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para)
{//设置本机MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);//设置UDP-A的对方MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);(heth->Instance)->MACA1HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收//设置UDP-B的对方MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);(heth->Instance)->MACA2HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收
}

我这里是希望为我的两个UDP精确过滤接收到的源地址

所以AE位设置为1,SA设置为1,MBC全部为0(MAC地址全部检查)

假如我希望过滤MAC中特定的厂家字段

例如某个MAC地址

01-02-03-04-05-06

其中01-02-03就是厂家字段

那么代码要这样修改(MBC的第29位,28位,27位置1)

这样MAC层就不会检查MAC地址里后3个字节(04-05-06)

但是会检查前3个字节,也就是厂家字段

这里需要注意MAC地址的字节序

static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para)
{//设置本机MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);//设置UDP-A的对方MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);(heth->Instance)->MACA1HR|=0xF8000000;//需要匹配厂家字段//设置UDP-B的对方MAC地址ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);(heth->Instance)->MACA2HR|=0xF8000000;//需要匹配厂家字段
}

然后这些函数的调用顺序按:

1. HAL_ETH_Init

2. ETH_MAC_Setting

3. ETH_DMA_Setting

4. ETH_MAC_Filter_Setting

最后关于HASH表过滤

参考这位兄弟的帖子https://blog.csdn.net/freege9/article/details/91044630

他是F429的,不过原理类似

原理大概是这样的

用你希望过滤的MAC传递到一个Hash计算函数里,得到一个值,通过这个值产生“映射”关系来过滤MAC地址,所以这个并不是精确的,因为可能会重复~~

HASH函数

函数

/ STM32 MACHASH - Copyright (C) 2014-2018 Clive Turvey (sourcer32@gmail.com)
//  All Rights Reserved#include <windows.h>#include <stdio.h>
#include <stdlib.h>typedef unsigned char uint8_t;
typedef unsigned long uint32_t;uint32_t Rev32(uint32_t x)
{uint32_t y;int i;y = 0;for(i=0; i<32; i++)if (x & (1 << i))y |= 1 << (31 - i);return(y);
}uint32_t MacHash(const uint8_t *Mac) // sourcer32@gmail.com
{int i, j;uint32_t Crc;Crc = 0xFFFFFFFF;for(j=0; j<6; j++){Crc = Crc ^ (uint32_t)Mac[j];for(i=0; i<8; i++)if (Crc & 1)Crc = (Crc >> 1) ^ 0xEDB88320; // Reversed 0x04C11DB7elseCrc = (Crc >> 1);}return(Rev32(~Crc) >> 26); // Get High order 6-bit in reversed/inverted CRC
}uint32_t MacHashFast(const uint8_t *Mac) // sourcer32@gmail.com
{static const uint32_t Rev6Tbl[] = {0x00,0x20,0x10,0x30,0x08,0x28,0x18,0x38,0x04,0x24,0x14,0x34,0x0C,0x2C,0x1C,0x3C,0x02,0x22,0x12,0x32,0x0A,0x2A,0x1A,0x3A,0x06,0x26,0x16,0x36,0x0E,0x2E,0x1E,0x3E,0x01,0x21,0x11,0x31,0x09,0x29,0x19,0x39,0x05,0x25,0x15,0x35,0x0D,0x2D,0x1D,0x3D,0x03,0x23,0x13,0x33,0x0B,0x2B,0x1B,0x3B,0x07,0x27,0x17,0x37,0x0F,0x2F,0x1F,0x3F };static const uint32_t Crc32Tbl[] = {0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0,0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320,0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190,0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000 };int i;uint32_t Crc;Crc = 0;for(i=0; i<6; i++){Crc = Crc ^ (uint32_t)Mac[i];Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F];  /* lower nibble */Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F];  /* upper nibble */}return(Rev6Tbl[Crc & 0x3F]);
}int main(int argc, char **argv)
{static const uint8_t Test1[] = { 0x1F, 0x52, 0x41, 0x9C, 0xB6, 0xAF }; // 0x2Cstatic const uint8_t Test2[] = { 0xA0, 0x0A, 0x98, 0x00, 0x00, 0x45 }; // 0x07static const uint8_t Test3[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x21 }; // 0x24printf("MacHash %02X\n", MacHash(Test1));printf("MacHash %02X\n", MacHash(Test2));printf("MacHash %02X\n", MacHash(Test3));printf("MacHashFast %02X\n", MacHashFast(Test1));printf("MacHashFast %02X\n", MacHashFast(Test2));printf("MacHashFast %02X\n", MacHashFast(Test3));return(1);
}

回到手册

上面的函数算出来一个数,假如是手册上的那个0x2c,二进制为101100B

换句看得懂的人话···就是:

算出来的数先看第6位

是1的话说明用到的是HASH表高位寄存器

否则用到的是HASH表低位寄存器

然后剩下的5位,转成十进制不是12嘛

如果你希望过滤这个MAC

那么你就把对应的HASH表高/低位寄存器的对应位置1,否则置0

这里的0x2c就是要把

HASH表高位寄存器的第12位置1

就可以过滤这条MAC了

然后把你希望的MAC地址都按照上面说的方法弄完

回到这个函数稍微改一下

uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth)
{ETH_MACInitTypeDef macinit;/* Ethernet MAC default initialization **************************************/macinit.Watchdog = ETH_WATCHDOG_ENABLE;macinit.Jabber = ETH_JABBER_ENABLE;macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE){macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;}else{macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;}macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE;    //使能重传macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE;      //使能自动去除macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE; //!!多播HASH完美过滤macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE; //!!单播HASH完美过滤macinit.HashTableHigh = 0x0; //!!填你最后算完的Hash表高位macinit.HashTableLow = 0x0; //!!填你最后算完的Hash表低位macinit.PauseTime = 0x0;macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;macinit.VLANTagIdentifier = 0x0;return HAL_ETH_ConfigMAC(heth, &macinit);
}

大概MAC层过滤就这些东西了

如果有条件弄MAC层过滤真的强烈建议开启,可以大幅减轻协议栈的处理负担,板卡不会因为处理大量无用的数据而白白浪费处理性能。

STM32 F7的MAC层过滤使用+实例代码相关推荐

  1. 关闭无限局域网配置服务器,无线局域网无线控制器MAC地址过滤配置实例-Cisco.PDF...

    无线局域网无线控制器MAC地址过滤配置实例-Cisco 无线局域网无线控制器MAC 地址过滤配置实例 简介2 先决条件2 要求2 组件使用2 无线控制器上的MAC 地址过滤(MAC 认证)2 在无线控 ...

  2. python协同过滤调用包_简单的python协同过滤程序实例代码

    本文研究的主要是python协同过滤程序的相关内容,具体介绍如下. 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看 ...

  3. 【协议分析】Wireshark 过滤表达式实例

    Wireshark 过滤表达式实例 1.wireshark基本的语法 字符 \d          0-9的数字 \D          \d的补集(以所以字符为全集,下同),即所有非数字的字符 \w ...

  4. Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platfrom))

    catalog 0.引言 1.Windows 2000网络结构和OSI模型 2.NDIS驱动 3.NDIS微端口驱动编程实例 4.NDIS中间层驱动编程实例 5.TDI驱动 6.TDI驱动 7.TDI ...

  5. 破解路由器基于MAC地址过滤策略的方法

    众所周知,路由器可通过设置MAC地址过滤策略来限制上网设备.而MAC地址又是全球唯一的,如笔记本网卡的MAC地址在出厂时就被烧入了一串独一无二的数字(如97-AB-DE-23-45-67),既然MAC ...

  6. 以太网的信道利用率与MAC层详解

    集线器 使用集线器的星型拓扑 集线器由于采用了大规模集成电路芯片,所以可靠性大大提高. 1990年,IEEE针对星型以太网制定了10BASE-T标准,即802.3i 其中,10代表10Mb/s,BAS ...

  7. [4G5G专题-96]:MAC层- 调度 - 下行调度的原理、过程与算法

    目录 第1章 调度概述 1.1 下行调度概述 1.2 无线资源调度的分类 第2章 下行调度的整体架构与过程 2.1 上行需要调度的信道 2.2 下行数据发送过程 2.3 下行调度架构 2.4 下行调度 ...

  8. java 获取用户的MAC地址多种方法实例详解

    java 获取用户的MAC地址多种方法实例详解 这篇文章主要介绍了JAVA实现获取用户的MAC地址的多种方法实例,需要的朋友可以参考下 java实现获取用户的MAC地址方法: 方法一:将本机地址与局域 ...

  9. 第4节:ZigBee MAC层介绍

    1.MAC层: 1):提供两种服务:通过MAC层管理实体接口(MLME SAP)向MAC层数据和MAC层管理提供服务 2):MAC层特征:信标管理,信道接入,时隙管理,发送确认帧,发送连接和断开请求, ...

最新文章

  1. unique--求集合的单值元素
  2. 用python让excel飞起来 pdf_电脑卡?用u盘制作一个提速工具飞起来
  3. 嵌入式电路设计(电路仿真)
  4. linux java缓存失效_转载:Linux服务器Cache占用过多内存导致系统内存不足最终java应用程序崩溃解决方案...
  5. 字符串是单一字符的无序组合吗_Python中拼接字符串的多种方法, 你想了解吗?...
  6. html+表格+左侧表头,HTML多表头表格代码
  7. 手把手教你学DSP 28335学习笔记
  8. 开关电源PFC电路原理详解及matlab仿真
  9. ps怎么把模糊的图片变清楚
  10. 阿里云部署网站全流程(基于nodejs)
  11. 计算机专业大学排名及本科录取分数线,计算机专业高考多少分录取?附中国计算机专业大学排名及分数线...
  12. 「电商干货」分销爆单的6个步骤
  13. 两个PDF怎么合并一个pdf
  14. iMazing中IPA文件的介绍与管理
  15. free掉结点一定会造成断链吗?
  16. 内蒙古对口升学2018年计算机,2018年届对口升学考试计算机专业月考三试题.doc
  17. 小米air2se耳机只有一边有声音怎么办_盘点2020半入耳蓝牙耳机排名
  18. 日语语法笔记【翻译】
  19. http请求HttpServletRequest详解
  20. 大学计算机实验六实验报告,大学计算机实验6 实验报告.pdf

热门文章

  1. 标签平滑深度学习:Google Brain解释了为什么标签平滑有用以及什么时候使用它(SOTA tips)​...
  2. ntldr is compressed 解决方法 attrib -c ntldr
  3. 数据分析报告1:某电商店铺印度销售情况分析
  4. linux好压iso压缩文件,好压压缩文件管理器新手指南
  5. NXP_RT1172 eFlexPWM 模块简介
  6. 手机摄影最常用的 5 种构图方式
  7. 某2U机型中Intel X540T2 10G 网卡测试心得
  8. Asp.net Core3.0-------------------EntityFrameWork DbFirst
  9. TMC260系列电机驱动芯片应用介绍
  10. 如何查询银行卡归属地?