mirror of
https://github.com/apache/nuttx.git
synced 2026-08-02 12:49:00 +00:00
otherwise, if the mld timers are not cancelled, an illegal address will be accessed after timeout. to avoid this scenario, when the network card is unregistered, all MLD timers must be attempted to be synchronously cancelled. Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
523 lines
20 KiB
C
523 lines
20 KiB
C
/****************************************************************************
|
|
* net/mld/mld.h
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/* State transition diagram for a router in Querier state (RFC 2710):
|
|
* ________________
|
|
* | |
|
|
* | |timer expired
|
|
* timer expired| |(notify routing -,
|
|
* (notify routing -)| No Listeners |clear rxmt tmr)
|
|
* ------->| Present |<---------
|
|
* | | | |
|
|
* | | | |
|
|
* | |________________| | ---------------
|
|
* | | | | rexmt timer |
|
|
* | report received| | | expired |
|
|
* | (notify routing +,| | | (send m-a-s |
|
|
* | start timer)| | | query, |
|
|
* __________|______ | ________|_|______ st rxmt |
|
|
* | |<------------ | | tmr) |
|
|
* | | | |<-------
|
|
* | | report received | |
|
|
* | | (start timer, | |
|
|
* | | clear rxmt tmr) | |
|
|
* | Listeners |<-------------------| Checking |
|
|
* | Present | done received | Listeners |
|
|
* | | (start timer*, | |
|
|
* | | start rxmt timer, | |
|
|
* | | send m-a-s query) | |
|
|
* --->| |------------------->| |
|
|
* | |_________________| |_________________|
|
|
* | report received |
|
|
* | (start timer) |
|
|
* -----------------
|
|
*
|
|
* State transition diagram for a router in Non-Querier state is
|
|
* similar, but non-Queriers do not send any messages and are only
|
|
* driven by message reception.
|
|
*
|
|
* ________________
|
|
* | |
|
|
* | |
|
|
* timer expired| |timer expired
|
|
* (notify routing -)| No Listeners |(notify routing -)
|
|
* --------->| Present |<---------
|
|
* | | | |
|
|
* | | | |
|
|
* | | | |
|
|
* | |________________| |
|
|
* | | |
|
|
* | |report received |
|
|
* | |(notify routing +,|
|
|
* | | start timer) |
|
|
* ________|________ | ________|________
|
|
* | |<--------- | |
|
|
* | | report received | |
|
|
* | | (start timer) | |
|
|
* | Listeners |<-------------------| Checking |
|
|
* | Present | m-a-s query rec'd | Listeners |
|
|
* | | (start timer*) | |
|
|
* ---->| |------------------->| |
|
|
* | |_________________| |_________________|
|
|
* | report received |
|
|
* | (start timer) |
|
|
* -----------------
|
|
*/
|
|
|
|
#ifndef __NET_MLD_MLD_H
|
|
#define __NET_MLD_MLD_H
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <debug.h>
|
|
|
|
#include <nuttx/semaphore.h>
|
|
#include <nuttx/wqueue.h>
|
|
#include <nuttx/net/ip.h>
|
|
#include <nuttx/wdog.h>
|
|
|
|
#include "devif/devif.h"
|
|
#include "socket/socket.h"
|
|
|
|
#ifdef CONFIG_NET_MLD
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Global flags */
|
|
|
|
#define MLD_QUERIER (1 << 0) /* Querier */
|
|
#define MLD_V1COMPAT (1 << 1) /* MLDv1 compatibility mode */
|
|
#define MLD_GENPEND (1 << 2) /* General query pending */
|
|
|
|
#define SET_MLD_QUERIER(f) do { (f) |= MLD_QUERIER; } while (0)
|
|
#define SET_MLD_V1COMPAT(f) do { (f) |= MLD_V1COMPAT; } while (0)
|
|
#define SET_MLD_GENPEND(f) do { (f) |= MLD_GENPEND; } while (0)
|
|
|
|
#define CLR_MLD_QUERIER(f) do { (f) &= ~MLD_QUERIER; } while (0)
|
|
#define CLR_MLD_V1COMPAT(f) do { (f) &= ~MLD_V1COMPAT; } while (0)
|
|
#define CLR_MLD_GENPEND(f) do { (f) &= ~MLD_GENPEND; } while (0)
|
|
|
|
#define IS_MLD_QUERIER(f) (((f) & MLD_QUERIER) != 0)
|
|
#define IS_MLD_V1COMPAT(f) (((f) & MLD_V1COMPAT) != 0)
|
|
#define IS_MLD_GENPEND(f) (((f) & MLD_GENPEND) != 0)
|
|
|
|
/* Group flags */
|
|
|
|
#define MLD_STARTUP (1 << 1) /* Startup unsolicited Reports */
|
|
#define MLD_LASTREPORT (1 << 3) /* We were the last to report */
|
|
#define MLD_SCHEDMSG (1 << 4) /* Outgoing message scheduled */
|
|
#define MLD_WAITMSG (1 << 5) /* Block until message sent */
|
|
#define MLD_RPTPEND (1 << 6) /* Report pending */
|
|
|
|
#define SET_MLD_STARTUP(f) do { (f) |= MLD_STARTUP; } while (0)
|
|
#define SET_MLD_LASTREPORT(f) do { (f) |= MLD_LASTREPORT; } while (0)
|
|
#define SET_MLD_SCHEDMSG(f) do { (f) |= MLD_SCHEDMSG; } while (0)
|
|
#define SET_MLD_WAITMSG(f) do { (f) |= MLD_WAITMSG; } while (0)
|
|
#define SET_MLD_RPTPEND(f) do { (f) |= MLD_RPTPEND; } while (0)
|
|
|
|
#define CLR_MLD_STARTUP(f) do { (f) &= ~MLD_STARTUP; } while (0)
|
|
#define CLR_MLD_LASTREPORT(f) do { (f) &= ~MLD_LASTREPORT; } while (0)
|
|
#define CLR_MLD_SCHEDMSG(f) do { (f) &= ~MLD_SCHEDMSG; } while (0)
|
|
#define CLR_MLD_WAITMSG(f) do { (f) &= ~MLD_WAITMSG; } while (0)
|
|
#define CLR_MLD_RPTPEND(f) do { (f) &= ~MLD_RPTPEND; } while (0)
|
|
|
|
#define IS_MLD_STARTUP(f) (((f) & MLD_STARTUP) != 0)
|
|
#define IS_MLD_LASTREPORT(f) (((f) & MLD_LASTREPORT) != 0)
|
|
#define IS_MLD_SCHEDMSG(f) (((f) & MLD_SCHEDMSG) != 0)
|
|
#define IS_MLD_WAITMSG(f) (((f) & MLD_WAITMSG) != 0)
|
|
#define IS_MLD_RPTPEND(f) (((f) & MLD_RPTPEND) != 0)
|
|
|
|
/* Debug ********************************************************************/
|
|
|
|
#ifdef CONFIG_NET_MLD_DEBUG
|
|
# define mlderr _err
|
|
# define mldwarn _warn
|
|
# define mldinfo _info
|
|
#else
|
|
# define mlderr nerr
|
|
# define mldwarn nwarn
|
|
# define mldinfo ninfo
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Type Definitions
|
|
****************************************************************************/
|
|
|
|
/* These are the types of messages that may be sent in response to a device
|
|
* poll.
|
|
*/
|
|
|
|
enum mld_msgtype_e
|
|
{
|
|
MLD_SEND_NONE = 0, /* Nothing to send */
|
|
MLD_SEND_GENQUERY, /* Send General Query */
|
|
MLD_SEND_MASQUERY, /* Send General Query */
|
|
MLD_SEND_V1REPORT, /* Send MLDv1 Report message */
|
|
MLD_SEND_V2REPORT, /* Send MLDv2 Report message */
|
|
MLD_SEND_DONE /* Send Done message */
|
|
};
|
|
|
|
/* This structure represents one group member. There is a list of groups
|
|
* for each device interface structure.
|
|
*/
|
|
|
|
struct mld_group_s
|
|
{
|
|
struct mld_group_s *next; /* Implements a singly-linked list */
|
|
net_ipv6addr_t grpaddr; /* Group IPv6 address */
|
|
struct work_s work; /* For deferred timeout operations */
|
|
struct wdog_s polldog; /* Timer used for periodic or delayed events */
|
|
sem_t sem; /* Used to wait for message transmission */
|
|
#ifdef CONFIG_NET_MLD_ROUTER
|
|
uint16_t members; /* Number of members currently reporting (excludes us) */
|
|
uint16_t lstmbrs; /* Number of members reporting (last query) */
|
|
#endif
|
|
uint8_t ifindex; /* Interface index */
|
|
uint8_t flags; /* See MLD_ flags definitions */
|
|
uint8_t msgtype; /* Pending message type to send (if non-zero) */
|
|
uint8_t count; /* Reports remaining in repetition count */
|
|
uint8_t njoins; /* Number of joins from this host */
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Public Data
|
|
****************************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
# define EXTERN extern "C"
|
|
extern "C"
|
|
{
|
|
#else
|
|
# define EXTERN extern
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Function Prototypes
|
|
****************************************************************************/
|
|
|
|
struct ipv6_mreq; /* Forward reference */
|
|
struct net_driver_s; /* Forward reference */
|
|
struct mld_mcast_listen_query_s; /* Forward reference */
|
|
struct mld_mcast_listen_report_v1_s; /* Forward reference */
|
|
struct mld_mcast_listen_report_v2_s; /* Forward reference */
|
|
struct mld_mcast_listen_done_s; /* Forward reference */
|
|
|
|
/****************************************************************************
|
|
* Name: mld_devinit
|
|
*
|
|
* Description:
|
|
* Called when a new network device is registered to configure that device
|
|
* for MLD support.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_devinit(FAR struct net_driver_s *dev);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_query
|
|
*
|
|
* Description:
|
|
* Called from icmpv6_input() when a Multicast Listener Query is received.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_query(FAR struct net_driver_s *dev,
|
|
FAR const struct mld_mcast_listen_query_s *query);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_report_v1
|
|
*
|
|
* Description:
|
|
* Called from icmpv6_input() when a MLDv1 Multicast Listener Report is
|
|
* received.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_report_v1(FAR struct net_driver_s *dev,
|
|
FAR const struct mld_mcast_listen_report_v1_s *report);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_report_v2
|
|
*
|
|
* Description:
|
|
* Called from icmpv6_input() when a Version 2 Multicast Listener Report is
|
|
* received.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_report_v2(FAR struct net_driver_s *dev,
|
|
FAR const struct mld_mcast_listen_report_v2_s *report);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_done
|
|
*
|
|
* Description:
|
|
* Called from icmpv6_input() when a Multicast Listener Done is received.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_done(FAR struct net_driver_s *dev,
|
|
FAR const struct mld_mcast_listen_done_s *done);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_grpalloc
|
|
*
|
|
* Description:
|
|
* Allocate a new group from heap memory.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct mld_group_s *mld_grpalloc(FAR struct net_driver_s *dev,
|
|
FAR const net_ipv6addr_t addr);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_grpfind
|
|
*
|
|
* Description:
|
|
* Find an existing group.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct mld_group_s *mld_grpfind(FAR struct net_driver_s *dev,
|
|
FAR const net_ipv6addr_t addr);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_grpallocfind
|
|
*
|
|
* Description:
|
|
* Find an existing group. If not found, create a new group for the
|
|
* address.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct mld_group_s *mld_grpallocfind(FAR struct net_driver_s *dev,
|
|
FAR const net_ipv6addr_t addr);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_grpfree
|
|
*
|
|
* Description:
|
|
* Release a previously allocated group.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_grpfree(FAR struct net_driver_s *dev,
|
|
FAR struct mld_group_s *group);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_grpfree_all
|
|
*
|
|
* Description:
|
|
* Release all previously allocated groups for a device.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_grpfree_all(FAR struct net_driver_s *dev);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_new_pollcycle
|
|
*
|
|
* Description:
|
|
* Update accumulated membership at the beginning of each new poll cycle
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_NET_MLD_ROUTER
|
|
void mld_new_pollcycle(FAR struct net_driver_s *dev);
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Name: mld_schedmsg
|
|
*
|
|
* Description:
|
|
* Schedule a message to be send at the next driver polling interval.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_schedmsg(FAR struct mld_group_s *group, uint8_t msgtype);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_waitmsg
|
|
*
|
|
* Description:
|
|
* Schedule a message to be send at the next driver polling interval and
|
|
* block, waiting for the message to be sent.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_waitmsg(FAR struct mld_group_s *group, uint8_t msgtype);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_poll
|
|
*
|
|
* Description:
|
|
* Poll the groups associated with the device to see if any MLD messages
|
|
* are pending transfer.
|
|
*
|
|
* Returned Value:
|
|
* Returns a non-zero value if a IGP message is sent.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_poll(FAR struct net_driver_s *dev);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_send
|
|
*
|
|
* Description:
|
|
* Sends an MLD IP packet on a network interface. This function constructs
|
|
* the IP header and calculates the IP header checksum.
|
|
*
|
|
* Input Parameters:
|
|
* dev - The device driver structure to use in the send operation.
|
|
* group - Describes the multicast group member and identifies the
|
|
* message to be sent.
|
|
* msgtype - The type of the message to be sent (see enum mld_msgtype_e)
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|
uint8_t msgtype);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_report_msgtype
|
|
*
|
|
* Description:
|
|
* Determine which type of Report to send, MLDv1 or MLDv2, depending on
|
|
* current state of compatibility mode flag.
|
|
*
|
|
****************************************************************************/
|
|
|
|
uint8_t mld_report_msgtype(FAR struct net_driver_s *dev);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_joingroup
|
|
*
|
|
* Description:
|
|
* Add the specified group address to the group. This function
|
|
* implements the logic for the IPV6_JOIN_GROUP socket option.
|
|
*
|
|
* The IPV6_JOIN_GROUP socket option is used to join a multicast group.
|
|
* This is accomplished by using the setsockopt() API and specifying the
|
|
* address of the ipv6_mreq structure containing the IPv6 multicast address
|
|
* and the local IPv6 multicast interface index. The stack chooses a
|
|
* default multicast interface if an interface index of 0 is passed. The
|
|
* values specified in the IPV6_MREQ structure used by IPV6_JOIN_GROUP
|
|
* and IPV6_LEAVE_GROUP must be symmetrical. The format of the ipv6_mreq
|
|
* structure can be found in include/netinet/in.h
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_joingroup(FAR const struct ipv6_mreq *mrec);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_leavegroup
|
|
*
|
|
* Description:
|
|
* Remove the specified group address to the group. This function
|
|
* implements the logic for the IPV6_LEAVE_GROUP socket option.
|
|
*
|
|
* The IPV6_JOIN_GROUP socket option is used to join a multicast group.
|
|
* This is accomplished by using the setsockopt() API and specifying the
|
|
* address of the ipv6_mreq structure containing the IPv6 multicast address
|
|
* and the local IPv6 multicast interface index. The stack chooses a
|
|
* default multicast interface if an interface index of 0 is passed. The
|
|
* values specified in the IPV6_MREQ structure used by IPV6_JOIN_GROUP
|
|
* and IPV6_LEAVE_GROUP must be symmetrical. The format of the ipv6_mreq
|
|
* structure can be found in include/netinet/in.h
|
|
*
|
|
****************************************************************************/
|
|
|
|
int mld_leavegroup(FAR const struct ipv6_mreq *mrec);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_start_gentimer
|
|
*
|
|
* Description:
|
|
* Start/Re-start the general query timer.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_start_gentimer(FAR struct net_driver_s *dev, clock_t ticks);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_start_v1timer
|
|
*
|
|
* Description:
|
|
* Start the MLDv1 compatibility timer.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_start_v1timer(FAR struct net_driver_s *dev, clock_t ticks);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_start_polltimer
|
|
*
|
|
* Description:
|
|
* Start the MLD poll timer.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_start_polltimer(FAR struct mld_group_s *group, clock_t ticks);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_addmcastmac
|
|
*
|
|
* Description:
|
|
* Add an MLD MAC address to the device's MAC filter table.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_addmcastmac(FAR struct net_driver_s *dev,
|
|
FAR const net_ipv6addr_t ipaddr);
|
|
|
|
/****************************************************************************
|
|
* Name: mld_removemcastmac
|
|
*
|
|
* Description:
|
|
* Remove an MLD MAC address from the device's MAC filter table.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void mld_removemcastmac(FAR struct net_driver_s *dev,
|
|
FAR const net_ipv6addr_t ipaddr);
|
|
|
|
#undef EXTERN
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* CONFIG_NET_MLD */
|
|
#endif /* __NET_MLD_MLD_H */
|