Rework IGMP and MLD6 code to store group info per-netif.

Reasoning:
- Makes code in single-netif case perform better and smaller
- IGMP / MLD6 code is a little bit easier to read and understand
- Easier to get multicast groups per netif when implementing drivers

Downside: In multi-netif mode, there are two more pointers on each netif, even if IGMP/MLD6 is not used on it. But these systems should not be so memory-constrained that this will matter.
This commit is contained in:
Dirk Ziegelmeier 2016-09-21 13:33:33 +02:00
parent c25de8f317
commit c7c6b7ce93
6 changed files with 126 additions and 150 deletions

View File

@ -97,14 +97,13 @@ Steve Reynolds
#include "string.h"
static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr);
static err_t igmp_remove_group(struct igmp_group *group);
static void igmp_timeout( struct igmp_group *group);
static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group);
static void igmp_timeout(struct netif *netif, struct igmp_group *group);
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif);
static void igmp_send(struct igmp_group *group, u8_t type);
static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type);
struct igmp_group* igmp_group_list;
static ip4_addr_t allsystems;
static ip4_addr_t allrouters;
@ -160,36 +159,24 @@ igmp_start(struct netif *netif)
err_t
igmp_stop(struct netif *netif)
{
struct igmp_group *group = igmp_group_list;
struct igmp_group *prev = NULL;
struct igmp_group *next;
struct igmp_group *group = netif_igmp_data(netif);
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL);
/* look for groups joined on this interface further down the list */
while (group != NULL) {
next = group->next;
/* is it a group joined on this interface? */
if (group->netif == netif) {
/* is it the first group of the list? */
if (group == igmp_group_list) {
igmp_group_list = next;
}
/* is there a "previous" group defined? */
if (prev != NULL) {
prev->next = next;
}
/* disable the group at the MAC level */
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
ip4_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
}
/* free group */
memp_free(MEMP_IGMP_GROUP, group);
} else {
/* change the "previous" */
prev = group;
struct igmp_group *next = group->next; /* avoid use-after-free below */
/* disable the group at the MAC level */
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
ip4_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
}
/* free group */
memp_free(MEMP_IGMP_GROUP, group);
/* move to "next" */
group = next;
}
@ -204,12 +191,12 @@ igmp_stop(struct netif *netif)
void
igmp_report_groups(struct netif *netif)
{
struct igmp_group *group = igmp_group_list;
struct igmp_group *group = netif_igmp_data(netif);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif));
while (group != NULL) {
if ((group->netif == netif) && (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
if (!(ip4_addr_cmp(&(group->group_address), &allsystems))) {
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
}
group = group->next;
@ -227,10 +214,10 @@ igmp_report_groups(struct netif *netif)
struct igmp_group *
igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
{
struct igmp_group *group = igmp_group_list;
struct igmp_group *group = netif_igmp_data(ifp);
while (group != NULL) {
if ((group->netif == ifp) && (ip4_addr_cmp(&(group->group_address), addr))) {
if (ip4_addr_cmp(&(group->group_address), addr)) {
return group;
}
group = group->next;
@ -265,15 +252,14 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
/* Group doesn't exist yet, create a new one */
group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
if (group != NULL) {
group->netif = ifp;
ip4_addr_set(&(group->group_address), addr);
group->timer = 0; /* Not running */
group->group_state = IGMP_GROUP_NON_MEMBER;
group->last_reporter_flag = 0;
group->use = 0;
group->next = igmp_group_list;
group->next = netif_igmp_data(ifp);
igmp_group_list = group;
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
}
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
@ -290,17 +276,17 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
* @return ERR_OK if group was removed from the list, an err_t otherwise
*/
static err_t
igmp_remove_group(struct igmp_group *group)
igmp_remove_group(struct netif* netif, struct igmp_group *group)
{
err_t err = ERR_OK;
/* Is it the first group? */
if (igmp_group_list == group) {
igmp_group_list = group->next;
if (netif_igmp_data(netif) == group) {
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next);
} else {
/* look for group further down the list */
struct igmp_group *tmpGroup;
for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
if (tmpGroup->next == group) {
tmpGroup->next = group->next;
break;
@ -381,10 +367,10 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
IGMP_STATS_INC(igmp.rx_general);
}
groupref = igmp_group_list;
groupref = netif_igmp_data(inp);
while (groupref) {
/* Do not send messages on the all systems group address! */
if ((groupref->netif == inp) && (!(ip4_addr_cmp(&(groupref->group_address), &allsystems)))) {
if (!(ip4_addr_cmp(&(groupref->group_address), &allsystems))) {
igmp_delaying_member(groupref, igmp->igmp_maxresp);
}
groupref = groupref->next;
@ -427,7 +413,7 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
break;
default:
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)group->netif));
igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp));
IGMP_STATS_INC(igmp.proterr);
break;
}
@ -515,7 +501,7 @@ igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
}
IGMP_STATS_INC(igmp.tx_join);
igmp_send(group, IGMP_V2_MEMB_REPORT);
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
@ -600,13 +586,13 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
/* If there is no other use of the group */
if (group->use <= 1) {
/* Remove the group from the list */
igmp_remove_group(group);
igmp_remove_group(netif, group);
/* If we are the last reporter for this group */
if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n"));
IGMP_STATS_INC(igmp.tx_leave);
igmp_send(group, IGMP_LEAVE_GROUP);
igmp_send(netif, group, IGMP_LEAVE_GROUP);
}
/* Disable the group at the MAC level */
@ -637,16 +623,21 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
void
igmp_tmr(void)
{
struct igmp_group *group = igmp_group_list;
struct netif *netif = netif_list;
while (group != NULL) {
if (group->timer > 0) {
group->timer--;
if (group->timer == 0) {
igmp_timeout(group);
while (netif != NULL) {
struct igmp_group *group = netif_igmp_data(netif);
while (group != NULL) {
if (group->timer > 0) {
group->timer--;
if (group->timer == 0) {
igmp_timeout(netif, group);
}
}
group = group->next;
}
group = group->next;
netif = netif->next;
}
}
@ -657,7 +648,7 @@ igmp_tmr(void)
* @param group an igmp_group for which a timeout is reached
*/
static void
igmp_timeout(struct igmp_group *group)
igmp_timeout(struct netif *netif, struct igmp_group *group)
{
/* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group
(unless it is the allsystems group) */
@ -665,10 +656,10 @@ igmp_timeout(struct igmp_group *group)
(!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)group->netif));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif));
IGMP_STATS_INC(igmp.tx_report);
igmp_send(group, IGMP_V2_MEMB_REPORT);
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
}
}
@ -748,7 +739,7 @@ igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
* @param type the type of igmp packet to send
*/
static void
igmp_send(struct igmp_group *group, u8_t type)
igmp_send(struct netif *netif, struct igmp_group *group, u8_t type)
{
struct pbuf* p = NULL;
struct igmp_msg* igmp = NULL;
@ -762,7 +753,7 @@ igmp_send(struct igmp_group *group, u8_t type)
igmp = (struct igmp_msg *)p->payload;
LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
(p->len >= sizeof(struct igmp_msg)));
ip4_addr_copy(src, *netif_ip4_addr(group->netif));
ip4_addr_copy(src, *netif_ip4_addr(netif));
if (type == IGMP_V2_MEMB_REPORT) {
dest = &(group->group_address);
@ -781,7 +772,7 @@ igmp_send(struct igmp_group *group, u8_t type)
igmp->igmp_checksum = 0;
igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
igmp_ip_output_if(p, &src, dest, group->netif);
igmp_ip_output_if(p, &src, dest, netif);
}
pbuf_free(p);

View File

@ -75,16 +75,11 @@
#define MLD6_GROUP_DELAYING_MEMBER 1
#define MLD6_GROUP_IDLE_MEMBER 2
/* The list of joined groups. */
struct mld_group* mld_group_list;
/* Forward declarations. */
static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr);
static err_t mld6_remove_group(struct mld_group *group);
static err_t mld6_remove_group(struct netif *netif, struct mld_group *group);
static void mld6_delayed_report(struct mld_group *group, u16_t maxresp);
static void mld6_send(struct mld_group *group, u8_t type);
static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type);
/**
@ -95,33 +90,21 @@ static void mld6_send(struct mld_group *group, u8_t type);
err_t
mld6_stop(struct netif *netif)
{
struct mld_group *group = mld_group_list;
struct mld_group *prev = NULL;
struct mld_group *next;
struct mld_group *group = netif_mld6_data(netif);
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL);
/* look for groups joined on this interface further down the list */
while (group != NULL) {
next = group->next;
/* is it a group joined on this interface? */
if (group->netif == netif) {
/* is it the first group of the list? */
if (group == mld_group_list) {
mld_group_list = next;
}
/* is there a "previous" group defined? */
if (prev != NULL) {
prev->next = next;
}
/* disable the group at the MAC level */
if (netif->mld_mac_filter != NULL) {
netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
}
/* free group */
memp_free(MEMP_MLD6_GROUP, group);
} else {
/* change the "previous" */
prev = group;
struct mld_group *next = group->next; /* avoid use-after-free below */
/* disable the group at the MAC level */
if (netif->mld_mac_filter != NULL) {
netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
}
/* free group */
memp_free(MEMP_MLD6_GROUP, group);
/* move to "next" */
group = next;
}
@ -136,12 +119,10 @@ mld6_stop(struct netif *netif)
void
mld6_report_groups(struct netif *netif)
{
struct mld_group *group = mld_group_list;
struct mld_group *group = netif_mld6_data(netif);
while (group != NULL) {
if (group->netif == netif) {
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
}
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
group = group->next;
}
}
@ -157,10 +138,10 @@ mld6_report_groups(struct netif *netif)
struct mld_group *
mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr)
{
struct mld_group *group = mld_group_list;
struct mld_group *group = netif_mld6_data(ifp);
while (group != NULL) {
if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) {
if (ip6_addr_cmp(&(group->group_address), addr)) {
return group;
}
group = group->next;
@ -185,15 +166,14 @@ mld6_new_group(struct netif *ifp, const ip6_addr_t *addr)
group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP);
if (group != NULL) {
group->netif = ifp;
ip6_addr_set(&(group->group_address), addr);
group->timer = 0; /* Not running */
group->group_state = MLD6_GROUP_IDLE_MEMBER;
group->last_reporter_flag = 0;
group->use = 0;
group->next = mld_group_list;
group->next = netif_mld6_data(ifp);
mld_group_list = group;
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group);
}
return group;
@ -206,17 +186,17 @@ mld6_new_group(struct netif *ifp, const ip6_addr_t *addr)
* @return ERR_OK if group was removed from the list, an err_t otherwise
*/
static err_t
mld6_remove_group(struct mld_group *group)
mld6_remove_group(struct netif *netif, struct mld_group *group)
{
err_t err = ERR_OK;
/* Is it the first group? */
if (mld_group_list == group) {
mld_group_list = group->next;
if (netif_mld6_data(netif) == group) {
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next);
} else {
/* look for group further down the list */
struct mld_group *tmpGroup;
for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
if (tmpGroup->next == group) {
tmpGroup->next = group->next;
break;
@ -264,10 +244,9 @@ mld6_input(struct pbuf *p, struct netif *inp)
ip6_addr_isany(&(mld_hdr->multicast_address))) {
MLD6_STATS_INC(mld6.rx_general);
/* Report all groups, except all nodes group, and if-local groups. */
group = mld_group_list;
group = netif_mld6_data(inp);
while (group != NULL) {
if ((group->netif == inp) &&
(!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
mld6_delayed_report(group, mld_hdr->max_resp_delay);
}
@ -376,7 +355,7 @@ mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
/* Report our membership. */
MLD6_STATS_INC(mld6.tx_report);
mld6_send(group, ICMP6_TYPE_MLR);
mld6_send(netif, group, ICMP6_TYPE_MLR);
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
}
@ -439,12 +418,12 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
/* Leave if there is no other use of the group */
if (group->use <= 1) {
/* Remove the group from the list */
mld6_remove_group(group);
mld6_remove_group(netif, group);
/* If we are the last reporter for this group */
if (group->last_reporter_flag) {
MLD6_STATS_INC(mld6.tx_leave);
mld6_send(group, ICMP6_TYPE_MLD);
mld6_send(netif, group, ICMP6_TYPE_MLD);
}
/* Disable the group at the MAC level */
@ -477,21 +456,25 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr)
void
mld6_tmr(void)
{
struct mld_group *group = mld_group_list;
struct netif *netif = netif_list;
while (group != NULL) {
if (group->timer > 0) {
group->timer--;
if (group->timer == 0) {
/* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
MLD6_STATS_INC(mld6.tx_report);
mld6_send(group, ICMP6_TYPE_MLR);
group->group_state = MLD6_GROUP_IDLE_MEMBER;
while (netif != NULL) {
struct mld_group *group = netif_mld6_data(netif);
while (group != NULL) {
if (group->timer > 0) {
group->timer--;
if (group->timer == 0) {
/* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
MLD6_STATS_INC(mld6.tx_report);
mld6_send(netif, group, ICMP6_TYPE_MLR);
group->group_state = MLD6_GROUP_IDLE_MEMBER;
}
}
}
group = group->next;
}
group = group->next;
}
}
@ -538,7 +521,7 @@ mld6_delayed_report(struct mld_group *group, u16_t maxresp)
* @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
*/
static void
mld6_send(struct mld_group *group, u8_t type)
mld6_send(struct netif *netif, struct mld_group *group, u8_t type)
{
struct mld_header *mld_hdr;
struct pbuf *p;
@ -559,13 +542,13 @@ mld6_send(struct mld_group *group, u8_t type)
}
/* Select our source address. */
if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
/* This is a special case, when we are performing duplicate address detection.
* We must join the multicast group, but we don't have a valid address yet. */
src_addr = IP6_ADDR_ANY6;
} else {
/* Use link-local address as source address. */
src_addr = netif_ip6_addr(group->netif, 0);
src_addr = netif_ip6_addr(netif, 0);
}
/* MLD message header pointer. */
@ -592,7 +575,7 @@ mld6_send(struct mld_group *group, u8_t type)
/* Send the packet out. */
MLD6_STATS_INC(mld6.xmit);
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif);
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif);
pbuf_free(p);
}

View File

@ -259,7 +259,7 @@ netif_add(struct netif *netif,
#endif /* LWIP_IPV6 */
NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
netif->flags = 0;
#if LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0)
#ifdef netif_get_client_data
memset(netif->client_data, 0, sizeof(netif->client_data));
#endif /* LWIP_NUM_NETIF_CLIENT_DATA */
#if LWIP_IPV6_AUTOCONFIG

View File

@ -74,8 +74,6 @@ extern "C" {
struct igmp_group {
/** next link */
struct igmp_group *next;
/** interface on which the group is active */
struct netif *netif;
/** multicast address */
ip4_addr_t group_address;
/** signifies we were the last person to report */
@ -88,9 +86,6 @@ struct igmp_group {
u8_t use;
};
/* Head of IGMP group list */
extern struct igmp_group* igmp_group_list;
/* Prototypes */
void igmp_init(void);
err_t igmp_start(struct netif *netif);
@ -104,6 +99,9 @@ err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr);
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr);
void igmp_tmr(void);
/* Get list of IGMP groups for netif */
#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP))
#ifdef __cplusplus
}
#endif

View File

@ -58,8 +58,6 @@ extern "C" {
struct mld_group {
/** next link */
struct mld_group *next;
/** interface on which the group is active */
struct netif *netif;
/** multicast address */
ip6_addr_t group_address;
/** signifies we were the last person to report */
@ -72,9 +70,6 @@ struct mld_group {
u8_t use;
};
/* Head of MLD group list */
extern struct mld_group* mld_group_list;
#define MLD6_TMR_INTERVAL 100 /* Milliseconds */
err_t mld6_stop(struct netif *netif);
@ -87,6 +82,9 @@ err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr);
err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr);
err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr);
/* Get list of MLD6 groups for netif */
#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6))
#ifdef __cplusplus
}
#endif

View File

@ -111,6 +111,12 @@ enum lwip_internal_netif_client_data_index
#endif
#if LWIP_AUTOIP
LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP,
#endif
#if LWIP_IGMP
LWIP_NETIF_CLIENT_DATA_INDEX_IGMP,
#endif
#if LWIP_IPV6_MLD
LWIP_NETIF_CLIENT_DATA_INDEX_MLD6,
#endif
LWIP_NETIF_CLIENT_DATA_INDEX_MAX
};
@ -201,6 +207,18 @@ typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif,
const ip6_addr_t *group, enum netif_mac_filter_action action);
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0)
u8_t netif_alloc_client_data_id(void);
/** @ingroup netif_cd
* Set client data. Obtain ID from netif_alloc_client_data_id().
*/
#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data)
/** @ingroup netif_cd
* Get client data. Obtain ID from netif_alloc_client_data_id().
*/
#define netif_get_client_data(netif, id) (netif)->client_data[(id)]
#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */
/** Generic data structure used for all lwIP network interfaces.
* The following fields should be filled in by the initialization
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
@ -257,7 +275,7 @@ struct netif {
/** This field can be set by the device driver and could point
* to state information for the device. */
void *state;
#if LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0)
#ifdef netif_get_client_data
void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA];
#endif
#if LWIP_IPV6_AUTOCONFIG
@ -424,18 +442,6 @@ void netif_poll_all(void);
err_t netif_input(struct pbuf *p, struct netif *inp);
#if LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0)
u8_t netif_alloc_client_data_id(void);
/** @ingroup netif_cd
* Set client data. Obtain ID from netif_alloc_client_data_id().
*/
#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data)
/** @ingroup netif_cd
* Get client data. Obtain ID from netif_alloc_client_data_id().
*/
#define netif_get_client_data(netif, id) (netif)->client_data[(id)]
#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */
#if LWIP_IPV6
/** @ingroup netif_ip6 */
#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i])))