| /**************************************************************************** |
| * 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_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 */ |