MCUXpresso_MIMXRT1052xxxxB/middleware/lwip/port/ethernetif_mmac.c
Yilin Sun c2668b7ca0
Update SDK to v2.13.0
Signed-off-by: Yilin Sun <imi415@imi.moe>
2023-01-26 09:35:56 +08:00

211 lines
4.7 KiB
C

/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ethernetif_mmac.h"
#include <stdint.h>
#include <stdbool.h>
#include "lwip/opt.h"
#include "fsl_device_registers.h"
#if LWIP_IPV6 && LWIP_IPV6_MLD
#define _NUM_MLD6_GROUP MEMP_NUM_MLD6_GROUP
#else
#define _NUM_MLD6_GROUP 0
#endif
#if LWIP_IGMP
#define _NUM_IGMP_GROUP MEMP_NUM_IGMP_GROUP
#else
#define _NUM_IGMP_GROUP 0
#endif
/**
* Maximal possible count of IPv4 and IPv6 multicast MAC addresses
* on all netifs.
*/
#if (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0))
#define MMAC_CNT 0 /* LPC does not support MAC filters. It can only allow or disable all multicast packets */
#else
#define MMAC_CNT ((_NUM_MLD6_GROUP) + (_NUM_IGMP_GROUP))
#endif
#if MMAC_CNT > 0
/**
* @brief MMAC reflist item.
*/
struct mmac_ref_item
{
uint8_t netif_num;
uint64_t mmac;
uint16_t ref_cnt;
};
/**
* @brief MAC reflist itself.
*/
static struct mmac_ref_item mmac_ref_list[MMAC_CNT];
static uint64_t mac_array_to_uint64(const uint8_t *mmac_arr)
{
int i;
uint64_t mmac = 0;
for (i = 0; i < 6; i++)
{
mmac <<= 8;
mmac |= ((uint64_t)mmac_arr[i] & 0xffU);
}
return mmac;
}
/**
* @brief Used to retrieve a new (upcoming) index in the MAC address filter list.
*
* @param netif A netif pointer.
* @return New index on success, -1 and fails an assertion if the list capacity
* has been reached.
*/
static int ethernetif_mmac_get_new_idx(void)
{
int i;
int idx_free = -1;
for (i = 0; i < MMAC_CNT; i++)
{
if (mmac_ref_list[i].ref_cnt <= 0)
{
idx_free = i;
break;
}
}
LWIP_ASSERT("Multicast MAC list out of space", idx_free >= 0);
return idx_free;
}
#endif /* #if MMAC_CNT > 0 */
int ethernetif_mmac_get_idx(const struct netif *netif_, const uint8_t *mmac_arr)
{
#if MMAC_CNT <= 0
(void)(netif_);
(void)(mmac_arr);
return -1;
#else /* #if MMAC_CNT <= 0 */
/* Convert the MAC address to a 64-bit integer */
uint64_t mmac = mac_array_to_uint64(mmac_arr);
if (netif_ == NULL || mmac == 0)
{
return -1;
}
/* Iterate over every item */
for (int i = 0; i < MMAC_CNT; i++)
{
if (mmac_ref_list[i].netif_num == netif_->num && mmac_ref_list[i].mmac == mmac)
{
/* Both the MAC address and the iface index match, this is the index */
return i;
}
}
/* No index found, return new item's index */
return ethernetif_mmac_get_new_idx();
#endif /* #if MMAC_CNT <= 0 */
}
bool ethernetif_mmac_is_new(const int idx)
{
#if MMAC_CNT <= 0
(void)idx;
return false;
#else
return mmac_ref_list[idx].mmac == 0;
#endif
}
bool ethernetif_mmac_is_pending(const int idx)
{
#if MMAC_CNT <= 0
(void)idx;
return false;
#else
return mmac_ref_list[idx].ref_cnt <= 1 && !ethernetif_mmac_is_new(idx);
#endif
}
status_t ethernetif_mmac_ref_inc(const struct netif *netif_, const uint8_t *mmac_arr, const int idx)
{
#if MMAC_CNT <= 0
(void)netif_;
(void)idx;
return kStatus_Fail;
#else /* #if MMAC_CNT <= 0 */
uint64_t mmac = mac_array_to_uint64(mmac_arr);
uint8_t netif_num = netif_->num;
if (netif_ == NULL || idx >= MMAC_CNT || idx < 0 || mmac == 0)
{
return kStatus_InvalidArgument;
}
if (!ethernetif_mmac_is_new(idx) && mmac_ref_list[idx].mmac != mmac)
{
/*
* Item with a given index exists (non-zero MAC address) and a different
* (inconsistent) MAC address has been given.
*/
return kStatus_InvalidArgument;
}
/* Simply fill the item, increment the refcounter and return. */
mmac_ref_list[idx].mmac = mmac;
mmac_ref_list[idx].netif_num = netif_num;
mmac_ref_list[idx].ref_cnt++;
return kStatus_Success;
#endif /* #if MMAC_CNT <= 0 */
}
status_t ethernetif_mmac_ref_dec(const struct netif *netif_, const int idx)
{
#if MMAC_CNT <= 0
(void)netif_;
(void)idx;
return kStatus_Fail;
#else
if (netif_ == NULL || idx < 0 || idx >= MMAC_CNT)
{
return kStatus_InvalidArgument;
}
if (mmac_ref_list[idx].mmac == 0)
{
/* Item is empty ("nonexistent"), this shouldn't happen */
return kStatus_InvalidArgument;
}
/* Decrease the refcounter. */
mmac_ref_list[idx].ref_cnt--;
if (mmac_ref_list[idx].ref_cnt == 0)
{
/*
* Refcounter does not indicate any references - "remove" the item and
* return as such.
*/
memset(&mmac_ref_list[idx], 0, sizeof(struct mmac_ref_item));
}
return kStatus_Success;
#endif /* #if MMAC_CNT <= 0 */
}