net/mld: Review and update all MLD message receipt logic. Also ripple changs that are, hopefully, improvements back to IGMP.
This commit is contained in:
parent
3eed2e01bc
commit
b1a61834d9
15 changed files with 440 additions and 298 deletions
|
@ -382,6 +382,7 @@ struct mld_stats_s
|
|||
net_stats_t mas_query_received; /* Multicast Address Specific QUERY received */
|
||||
net_stats_t massq_query_received; /* Multicast Address and Source Specific QUERY received */
|
||||
net_stats_t ucast_query_received; /* Unicast query received */
|
||||
net_stats_t bad_query_received; /* Unhandled query received */
|
||||
net_stats_t v1report_received; /* Version 1 REPORT packets received */
|
||||
net_stats_t v2report_received; /* Version 2 REPORT packets received */
|
||||
net_stats_t done_received; /* DONE packets received */
|
||||
|
|
|
@ -492,8 +492,6 @@ void icmpv6_input(FAR struct net_driver_s *dev,
|
|||
{
|
||||
goto icmpv6_drop_packet;
|
||||
}
|
||||
|
||||
goto icmpv6_send_nothing; /* REVISIT */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -507,8 +505,6 @@ void icmpv6_input(FAR struct net_driver_s *dev,
|
|||
{
|
||||
goto icmpv6_drop_packet;
|
||||
}
|
||||
|
||||
goto icmpv6_send_nothing; /* REVISIT */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -523,8 +519,6 @@ void icmpv6_input(FAR struct net_driver_s *dev,
|
|||
{
|
||||
goto icmpv6_drop_packet;
|
||||
}
|
||||
|
||||
goto icmpv6_send_nothing; /* REVISIT */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -538,8 +532,6 @@ void icmpv6_input(FAR struct net_driver_s *dev,
|
|||
{
|
||||
goto icmpv6_drop_packet;
|
||||
}
|
||||
|
||||
goto icmpv6_send_nothing; /* REVISIT */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -551,13 +543,17 @@ void icmpv6_input(FAR struct net_driver_s *dev,
|
|||
}
|
||||
}
|
||||
|
||||
ninfo("Outgoing ICMPv6 packet length: %d (%d)\n",
|
||||
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
g_netstats.icmpv6.sent++;
|
||||
g_netstats.ipv6.sent++;
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
ninfo("Outgoing ICMPv6 packet length: %d (%d)\n",
|
||||
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);
|
||||
|
||||
g_netstats.icmpv6.sent++;
|
||||
g_netstats.ipv6.sent++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
|
||||
icmpv6_type_error:
|
||||
|
|
|
@ -275,6 +275,7 @@ void igmp_poll(FAR struct net_driver_s *dev);
|
|||
* group - Describes the multicast group member and identifies the
|
||||
* message to be sent.
|
||||
* destipaddr - The IP address of the recipient of the message
|
||||
* msgid - ID of message to send
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
|
@ -285,7 +286,7 @@ void igmp_poll(FAR struct net_driver_s *dev);
|
|||
****************************************************************************/
|
||||
|
||||
void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
|
||||
FAR in_addr_t *dest);
|
||||
FAR in_addr_t *destipaddr, uint8_t msgid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: igmp_joingroup
|
||||
|
|
|
@ -137,16 +137,33 @@ void igmp_input(struct net_driver_s *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address */
|
||||
/* Find the group (or create a new one) using the incoming IP address.
|
||||
* If we are not a router (and I assume we are not), then can ignore
|
||||
* querys for and reports from groups that we are not a member of.
|
||||
*
|
||||
* REVISIT: Router support is not yet implemented.
|
||||
*/
|
||||
|
||||
destipaddr = net_ip4addr_conv32(IGMPBUF->destipaddr);
|
||||
|
||||
#ifdef CONFIG_IGMP_ROUTER
|
||||
group = igmp_grpallocfind(dev, &destipaddr);
|
||||
if (!group)
|
||||
if (group == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate/find group: %08x\n", destipaddr);
|
||||
nerr("ERROR: Failed to allocate group: %08x\n", destipaddr);
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
group = igmp_grpfind(dev, &destipaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
nwarn("WARNING: Ignoring group. We are not a member: %08x\n",
|
||||
destipaddr);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now handle the message based on the IGMP message type */
|
||||
|
||||
switch (IGMPBUF->type)
|
||||
|
@ -183,6 +200,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||
if (IGMPBUF->grpaddr == 0)
|
||||
{
|
||||
FAR struct igmp_group_s *member;
|
||||
bool rptsent = false;
|
||||
|
||||
/* This is the general query */
|
||||
|
||||
|
@ -196,6 +214,11 @@ void igmp_input(struct net_driver_s *dev)
|
|||
}
|
||||
|
||||
IGMP_STATINCR(g_netstats.igmp.query_received);
|
||||
|
||||
/* Two passes through the member list. On the first, just
|
||||
* perform IDLE member checks.
|
||||
*/
|
||||
|
||||
for (member = (FAR struct igmp_group_s *)dev->d_igmp_grplist.head;
|
||||
member;
|
||||
member = member->next)
|
||||
|
@ -213,6 +236,42 @@ void igmp_input(struct net_driver_s *dev)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* On the second time through, we send the Report in
|
||||
* response to the query. This has to be done twice because
|
||||
* because there is only a single packet buffer that is used
|
||||
* for both incoming and outgoing packets. When the report
|
||||
* is sent, it will clobber the incoming query. Any attempt
|
||||
* to send an additional Report would also clobber a preceding
|
||||
* report
|
||||
*
|
||||
* REVISIT: This is a design flaw: Only a single report can
|
||||
* be sent in this context because there is no mechanism to
|
||||
* preserve the incoming request nor to queue multiple
|
||||
* outgoing reports.
|
||||
*/
|
||||
|
||||
for (member = (FAR struct igmp_group_s *)dev->d_igmp_grplist.head;
|
||||
member;
|
||||
member = member->next)
|
||||
{
|
||||
/* Skip over the all systems group entry */
|
||||
|
||||
if (!net_ipv4addr_cmp(member->grpaddr, g_ipv4_allsystems))
|
||||
{
|
||||
/* Send one REPORT and break out of the loop. */
|
||||
|
||||
igmp_send(dev, member, &member->grpaddr,
|
||||
IGMPv2_MEMBERSHIP_REPORT);
|
||||
rptsent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rptsent)
|
||||
{
|
||||
goto noresponse;
|
||||
}
|
||||
}
|
||||
else /* if (IGMPBUF->grpaddr != 0) */
|
||||
{
|
||||
|
@ -223,13 +282,28 @@ void igmp_input(struct net_driver_s *dev)
|
|||
*/
|
||||
|
||||
IGMP_STATINCR(g_netstats.igmp.ucast_query);
|
||||
|
||||
grpaddr = net_ip4addr_conv32(IGMPBUF->grpaddr);
|
||||
group = igmp_grpallocfind(dev, &grpaddr);
|
||||
ticks = net_dsec2tick((int)IGMPBUF->maxresp);
|
||||
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
||||
group = igmp_grpfind(dev, &grpaddr);
|
||||
|
||||
if (group != NULL)
|
||||
{
|
||||
igmp_startticks(group, ticks);
|
||||
CLR_IDLEMEMBER(group->flags);
|
||||
ticks = net_dsec2tick((int)IGMPBUF->maxresp);
|
||||
|
||||
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
||||
{
|
||||
igmp_startticks(group, ticks);
|
||||
CLR_IDLEMEMBER(group->flags);
|
||||
}
|
||||
|
||||
/* Send the REPORT */
|
||||
|
||||
igmp_send(dev, group, &group->grpaddr,
|
||||
IGMPv2_MEMBERSHIP_REPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto noresponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,6 +323,11 @@ void igmp_input(struct net_driver_s *dev)
|
|||
igmp_startticks(group, ticks);
|
||||
CLR_IDLEMEMBER(group->flags);
|
||||
}
|
||||
|
||||
/* Send the REPORT */
|
||||
|
||||
igmp_send(dev, group, &group->grpaddr,
|
||||
IGMPv2_MEMBERSHIP_REPORT);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -265,15 +344,24 @@ void igmp_input(struct net_driver_s *dev)
|
|||
SET_IDLEMEMBER(group->flags);
|
||||
CLR_LASTREPORT(group->flags);
|
||||
}
|
||||
|
||||
goto noresponse;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
nwarn("WARNING: Unexpected msg %02x\n", IGMPBUF->type);
|
||||
goto noresponse;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
noresponse:
|
||||
dev->d_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IGMP */
|
||||
|
|
|
@ -90,7 +90,6 @@ static inline void igmp_sched_send(FAR struct net_driver_s *dev,
|
|||
dest = &group->grpaddr;
|
||||
ninfo("Send IGMPv2_MEMBERSHIP_REPORT, dest=%08x flags=%02x\n",
|
||||
*dest, group->flags);
|
||||
IGMP_STATINCR(g_netstats.igmp.report_sched);
|
||||
SET_LASTREPORT(group->flags); /* Remember we were the last to report */
|
||||
}
|
||||
else
|
||||
|
@ -99,12 +98,11 @@ static inline void igmp_sched_send(FAR struct net_driver_s *dev,
|
|||
dest = &g_ipv4_allrouters;
|
||||
ninfo("Send IGMP_LEAVE_GROUP, dest=%08x flags=%02x\n",
|
||||
*dest, group->flags);
|
||||
IGMP_STATINCR(g_netstats.igmp.leave_sched);
|
||||
}
|
||||
|
||||
/* Send the message */
|
||||
|
||||
igmp_send(dev, group, dest);
|
||||
igmp_send(dev, group, dest, group->msgid);
|
||||
|
||||
/* Indicate that the message has been sent */
|
||||
|
||||
|
@ -164,10 +162,6 @@ void igmp_poll(FAR struct net_driver_s *dev)
|
|||
/* Yes, create the IGMP message in the driver buffer */
|
||||
|
||||
igmp_sched_send(dev, group);
|
||||
|
||||
/* Mark the message as sent and break out */
|
||||
|
||||
CLR_SCHEDMSG(group->flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ static uint16_t igmp_chksum(FAR uint8_t *buffer, int buflen)
|
|||
* group - Describes the multicast group member and identifies the
|
||||
* message to be sent.
|
||||
* destipaddr - The IP address of the recipient of the message
|
||||
* msgid - ID of message to send
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
|
@ -115,9 +116,9 @@ static uint16_t igmp_chksum(FAR uint8_t *buffer, int buflen)
|
|||
****************************************************************************/
|
||||
|
||||
void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
|
||||
FAR in_addr_t *destipaddr)
|
||||
FAR in_addr_t *destipaddr, uint8_t msgid)
|
||||
{
|
||||
ninfo("msgid: %02x destipaddr: %08x\n", group->msgid, (int)*destipaddr);
|
||||
ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
|
||||
|
||||
/* The total length to send is the size of the IP and IGMP headers and 4
|
||||
* bytes for the ROUTER ALERT (and, eventually, the Ethernet header)
|
||||
|
@ -158,7 +159,7 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
|
|||
|
||||
/* Set up the IGMP message */
|
||||
|
||||
IGMPBUF->type = group->msgid;
|
||||
IGMPBUF->type = msgid;
|
||||
IGMPBUF->maxresp = 0;
|
||||
net_ipv4addr_hdrcopy(IGMPBUF->grpaddr, &group->grpaddr);
|
||||
|
||||
|
|
|
@ -370,10 +370,10 @@ void mld_poll(FAR struct net_driver_s *dev);
|
|||
* 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.
|
||||
* destipaddr - The IP address of the recipient of the message
|
||||
* 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
|
||||
|
@ -384,7 +384,7 @@ void mld_poll(FAR struct net_driver_s *dev);
|
|||
****************************************************************************/
|
||||
|
||||
void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
||||
FAR const net_ipv6addr_t dest);
|
||||
uint8_t msgtype);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mld_joingroup
|
||||
|
|
|
@ -81,17 +81,23 @@
|
|||
int mld_done_v1(FAR struct net_driver_s *dev,
|
||||
FAR const struct mld_mcast_listen_done_v1_s *done)
|
||||
{
|
||||
#ifdef CONFIG_MLD_ROUTER
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
FAR struct mld_group_s *group;
|
||||
|
||||
ninfo("Version 1 Multicast Listener Done\n");
|
||||
MLD_STATINCR(g_netstats.mld.done_received);
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address */
|
||||
/* The done message is sent to the link-local, all routers multicast
|
||||
* address. Find the group using the group address in the Done message.
|
||||
*/
|
||||
|
||||
group = mld_grpfind(dev, ipv6->destipaddr);
|
||||
group = mld_grpfind(dev, done->grpaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
return -ENOENT; /* REVISIT: Or should it return OK? */
|
||||
/* We know nothing of this group */
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Ignore the Done message is this is not a Querier */
|
||||
|
@ -106,6 +112,15 @@ int mld_done_v1(FAR struct net_driver_s *dev,
|
|||
|
||||
mld_grpfree(dev, group);
|
||||
}
|
||||
#else
|
||||
/* We are not a router so we can just ignore Done messages */
|
||||
|
||||
ninfo("Version 1 Multicast Listener Done\n");
|
||||
MLD_STATINCR(g_netstats.mld.done_received);
|
||||
#endif
|
||||
|
||||
/* Need to set d_len to zero to indication that nothing is being sent */
|
||||
|
||||
dev->d_len = 0;
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,15 @@ int mld_leavegroup(FAR const struct ipv6_mreq *mrec)
|
|||
|
||||
MLD_STATINCR(g_netstats.mld.leaves);
|
||||
|
||||
/* Send a leave if the flag is set according to the state diagram */
|
||||
/* Send a leave if the LASTREPORT flag is set for the group. If there
|
||||
* are other members of the group, then their reports will clear the
|
||||
* LAST REPORT flag. In this case we know that there are other
|
||||
* members of the group and we do not have to send the Done message.
|
||||
*
|
||||
* The router responds to the Done message with a multicast-address-s
|
||||
* pecific (MAS) Query. If any other node responds to the Query with a
|
||||
* Report message the there are still listeners present.
|
||||
*/
|
||||
|
||||
if (IS_MLD_LASTREPORT(group->flags))
|
||||
{
|
||||
|
|
|
@ -82,6 +82,8 @@ int mld_schedmsg(FAR struct mld_group_s *group, uint8_t msgtype)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Schedule the message */
|
||||
|
||||
group->msgtype = msgtype;
|
||||
SET_MLD_SCHEDMSG(group->flags);
|
||||
|
||||
|
@ -132,7 +134,7 @@ int mld_waitmsg(FAR struct mld_group_s *group, uint8_t msgtype)
|
|||
*/
|
||||
|
||||
DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
|
||||
if (ret != -EINTR && ret != -ECANCELED)
|
||||
if (ret != -EINTR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include <nuttx/net/ip.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "inet/inet.h"
|
||||
#include "mld/mld.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -71,63 +70,6 @@
|
|||
static inline void mld_sched_send(FAR struct net_driver_s *dev,
|
||||
FAR struct mld_group_s *group)
|
||||
{
|
||||
const net_ipv6addr_t *dest;
|
||||
|
||||
/* Check what kind of message we need to send. There are only three
|
||||
* possibilities:
|
||||
*/
|
||||
|
||||
if (group->msgtype == MLD_SEND_GENQUERY)
|
||||
{
|
||||
dest = &g_ipv6_allrouters;
|
||||
|
||||
ninfo("Send General Query, flags=%02x\n", group->flags);
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
}
|
||||
else if (group->msgtype == MLD_SEND_REPORT)
|
||||
{
|
||||
dest = &group->grpaddr;
|
||||
|
||||
ninfo("Send Report, flags=%02x\n", group->flags);
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
|
||||
SET_MLD_LASTREPORT(group->flags); /* Remember we were the last to report */
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGASSERT(group->msgtype == MLD_SEND_DONE);
|
||||
|
||||
dest = &g_ipv6_allrouters;
|
||||
|
||||
ninfo("Send Done message, flags=%02x\n", group->flags);
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
}
|
||||
|
||||
/* Send the message */
|
||||
|
||||
mld_send(dev, group, *dest);
|
||||
|
||||
/* Indicate that the message has been sent */
|
||||
|
||||
CLR_MLD_SCHEDMSG(group->flags);
|
||||
group->msgtype = 0;
|
||||
|
||||
/* If there is a thread waiting fore the message to be sent, wake it up */
|
||||
|
||||
if (IS_MLD_WAITMSG(group->flags))
|
||||
{
|
||||
ninfo("Awakening waiter\n");
|
||||
nxsem_post(&group->sem);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -171,13 +113,27 @@ void mld_poll(FAR struct net_driver_s *dev)
|
|||
|
||||
if (IS_MLD_SCHEDMSG(group->flags))
|
||||
{
|
||||
/* Yes, create the MLD message in the driver buffer */
|
||||
/* Yes.. create the MLD message in the driver buffer */
|
||||
|
||||
mld_sched_send(dev, group);
|
||||
mld_send(dev, group, group->msgtype);
|
||||
|
||||
/* Mark the message as sent and break out */
|
||||
/* Indicate that the message has been sent */
|
||||
|
||||
CLR_MLD_SCHEDMSG(group->flags);
|
||||
group->msgtype = MLD_SEND_NONE;
|
||||
|
||||
/* If there is a thread waiting fore the message to be sent, wake
|
||||
* it up.
|
||||
*/
|
||||
|
||||
if (IS_MLD_WAITMSG(group->flags))
|
||||
{
|
||||
ninfo("Awakening waiter\n");
|
||||
nxsem_post(&group->sem);
|
||||
}
|
||||
|
||||
/* And break out of the loop */
|
||||
|
||||
CLR_MLD_SCHEDMSG(group->flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if 0 /* Not used */
|
||||
static clock_t mld_mrc2mrd(uint16_t mrc)
|
||||
{
|
||||
uint32_t mrd; /* Units of milliseconds */
|
||||
|
@ -91,6 +92,7 @@ static clock_t mld_mrc2mrd(uint16_t mrc)
|
|||
|
||||
return MSEC2TICK((clock_t)mrd);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mld_cmpaddr
|
||||
|
@ -122,22 +124,21 @@ static bool mld_cmpaddr(FAR struct net_driver_s *dev,
|
|||
* Name: mld_check_querier
|
||||
*
|
||||
* Description:
|
||||
* Perform a numerical comparison of the IPv6 Source Address and the IPv6
|
||||
* address of the link. Return true if the source address is less than
|
||||
* the link address.
|
||||
* Check if we are still the querier for this group (assuming that we are
|
||||
* currently the querier). This comparies the IPv6 Source Address of the
|
||||
* query against and the IPv6 address of the link. Ff the source address
|
||||
* is numerically less than the link address, when we are no longer the
|
||||
* querier.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mld_check_querier(FAR struct net_driver_s *dev,
|
||||
FAR struct ipv6_hdr_s *ipv6,
|
||||
FAR struct mld_group_s *member,
|
||||
uint16_t mrc)
|
||||
FAR struct mld_group_s *group)
|
||||
{
|
||||
clock_t ticks;
|
||||
|
||||
/* Check if this member is a Querier */
|
||||
|
||||
if (IS_MLD_QUERIER(member->flags))
|
||||
if (IS_MLD_QUERIER(group->flags))
|
||||
{
|
||||
/* This is a querier, check if the IPv6 source address is numerically
|
||||
* less than the IPv6 address assigned to this link.
|
||||
|
@ -145,17 +146,20 @@ static void mld_check_querier(FAR struct net_driver_s *dev,
|
|||
|
||||
if (mld_cmpaddr(dev, ipv6->srcipaddr))
|
||||
{
|
||||
/* This is a querier, then switch to non-querier and set a timeout.
|
||||
* If additional queries are received within this timeout period,
|
||||
* then we need to revert to Querier.
|
||||
/* Are we past the start up phase (where the timer is used for a
|
||||
* different purpose)?
|
||||
*/
|
||||
|
||||
ticks = mld_mrc2mrd(mrc);
|
||||
if (mld_cmptimer(member, ticks))
|
||||
if (!IS_MLD_STARTUP(group->flags))
|
||||
{
|
||||
mld_starttimer(member, ticks);
|
||||
CLR_MLD_QUERIER(member->flags);
|
||||
/* Yes.. cancel the timer */
|
||||
|
||||
wd_cancel(group->wdog);
|
||||
}
|
||||
|
||||
/* Switch to non-Querier mode */
|
||||
|
||||
CLR_MLD_QUERIER(group->flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,120 +196,175 @@ int mld_query(FAR struct net_driver_s *dev,
|
|||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
FAR struct mld_group_s *group;
|
||||
uint16_t mrc;
|
||||
bool unspec;
|
||||
|
||||
ninfo("Multicast Listener Query\n");
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address */
|
||||
#if 0 /* Not used */
|
||||
/* Max Response Delay. The Max Response Code field specifies the maximum
|
||||
* allowed time before sending a responding report in units of 1/10 second.
|
||||
*/
|
||||
|
||||
group = mld_grpallocfind(dev, ipv6->destipaddr);
|
||||
if (group == NULL)
|
||||
mrc = NTOHS(query->mrc);
|
||||
#endif
|
||||
|
||||
/* There are three variants of the Query message (RFC 3810):
|
||||
*
|
||||
* 1. A "General Query" is sent by the Querier to learn which
|
||||
* multicast addresses have listeners on an attached link. In a
|
||||
* General Query, both the Multicast Address field and the Number
|
||||
* of Sources (N) field are zero.
|
||||
* 2. A "Multicast Address Specific Query" is sent by the Querier to
|
||||
* learn if a particular multicast address has any listeners on an
|
||||
* attached link. In a Multicast Address Specific Query, the
|
||||
* Multicast Address field contains the multicast address of
|
||||
* interest, while the Number of Sources (N) field is set to zero.
|
||||
* 3. A "Multicast Address and Source Specific Query" is sent by the
|
||||
* Querier to learn if any of the sources from the specified list for
|
||||
* the particular multicast address has any listeners on an attached
|
||||
* link or not. In a Multicast Address and Source Specific Query the
|
||||
* Multicast Address field contains the multicast address of
|
||||
* interest, while the Source Address [i] field(s) contain(s) the
|
||||
* source address(es) of interest.
|
||||
*
|
||||
* Another possibility is a Unicast query that is sent specifically
|
||||
* to our local IP address.
|
||||
*/
|
||||
|
||||
/* Check the destination address. This varies with the type of message
|
||||
* being sent:
|
||||
*
|
||||
* MESSAGE DESTINATION ADDRESS
|
||||
* General Query Message: The link-local, all nodes multicast address
|
||||
* MAS Query Messages: The group multicast address
|
||||
*/
|
||||
|
||||
/* Check for a General Query */
|
||||
|
||||
if (net_ipv6addr_cmp(ipv6->destipaddr, g_ipv6_allnodes) &&
|
||||
net_ipv6addr_cmp(query->grpaddr, g_ipv6_unspecaddr) &&
|
||||
query->nsources == 0)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate/find group\n");
|
||||
FAR struct mld_group_s *member;
|
||||
bool rptsent = false;
|
||||
|
||||
/* This is the general query */
|
||||
|
||||
ninfo("General multicast query\n");
|
||||
MLD_STATINCR(g_netstats.mld.gmq_query_received);
|
||||
|
||||
/* Two passes through the member list. On the first, just check if we
|
||||
* are still the querier for the qroup.
|
||||
*/
|
||||
|
||||
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
|
||||
member;
|
||||
member = member->next)
|
||||
{
|
||||
/* Skip over the all systems group entry */
|
||||
|
||||
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
|
||||
{
|
||||
/* Check if we are still the querier for this group */
|
||||
|
||||
mld_check_querier(dev, ipv6, member);
|
||||
}
|
||||
}
|
||||
|
||||
/* On the second time through, we send the Report in response to the
|
||||
* query. This has to be done twice because because there is only
|
||||
* a single packet buffer that is used for both incoming and outgoing
|
||||
* packets. When the report is sent, it will clobber the incoming
|
||||
* query. Any attempt to send an additional Report would also clobber
|
||||
* a preceding report
|
||||
*
|
||||
* REVISIT: This is a design flaw: Only a single report can be sent
|
||||
* in this context because there is no mechanism to preserve the
|
||||
* incoming request nor to queue multiple outgoing reports.
|
||||
*/
|
||||
|
||||
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
|
||||
member;
|
||||
member = member->next)
|
||||
{
|
||||
/* Skip over the all systems group entry */
|
||||
|
||||
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
|
||||
{
|
||||
/* Send one report and break out of the loop */
|
||||
|
||||
mld_send(dev, member, MLD_SEND_REPORT);
|
||||
rptsent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to set d_len to zero if nothing is being sent */
|
||||
|
||||
if (!rptsent)
|
||||
{
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Find the group using associated with this group address. For the purpose
|
||||
* of sending reports, we only care about the query if we are a member of
|
||||
* the group.
|
||||
*/
|
||||
|
||||
group = mld_grpfind(dev, query->grpaddr);
|
||||
if (group != NULL)
|
||||
{
|
||||
ninfo("We are not a member of this group\n");
|
||||
|
||||
dev->d_len = 0;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Max Response Time. The Max Response Time field is meaningful only in
|
||||
* Query messages, and specifies the maximum allowed time before sending
|
||||
* a responding report in units of 1/10 second. In all other messages,
|
||||
* it is set to zero by the sender and ignored by receivers.
|
||||
*/
|
||||
/* Check if we are still the querier for this group */
|
||||
|
||||
/* Check if the query was sent to all systems */
|
||||
mld_check_querier(dev, ipv6, group);
|
||||
|
||||
unspec = net_ipv6addr_cmp(query->grpaddr, g_ipv6_unspecaddr);
|
||||
mrc = NTOHS(query->mrc);
|
||||
/* Check for Multicast Address Specific Query */
|
||||
|
||||
if (net_ipv6addr_cmp(ipv6->destipaddr, g_ipv6_allnodes))
|
||||
if (net_ipv6addr_cmp(ipv6->destipaddr, g_ipv6_allrouters))
|
||||
{
|
||||
/* There are three variants of the Query message (RFC 3810):
|
||||
*
|
||||
* 1. A "General Query" is sent by the Querier to learn which
|
||||
* multicast addresses have listeners on an attached link. In a
|
||||
* General Query, both the Multicast Address field and the Number
|
||||
* of Sources (N) field are zero.
|
||||
* 2. A "Multicast Address Specific Query" is sent by the Querier to
|
||||
* learn if a particular multicast address has any listeners on an
|
||||
* attached link. In a Multicast Address Specific Query, the
|
||||
* Multicast Address field contains the multicast address of
|
||||
* interest, while the Number of Sources (N) field is set to zero.
|
||||
* 3. A "Multicast Address and Source Specific Query" is sent by the
|
||||
* Querier to learn if any of the sources from the specified list for
|
||||
* the particular multicast address has any listeners on an attached
|
||||
* link or not. In a Multicast Address and Source Specific Query the
|
||||
* Multicast Address field contains the multicast address of
|
||||
* interest, while the Source Address [i] field(s) contain(s) the
|
||||
* source address(es) of interest.
|
||||
*/
|
||||
|
||||
if (unspec && query->nsources == 0)
|
||||
{
|
||||
FAR struct mld_group_s *member;
|
||||
|
||||
/* This is the general query */
|
||||
|
||||
ninfo("General multicast query\n");
|
||||
MLD_STATINCR(g_netstats.mld.gmq_query_received);
|
||||
|
||||
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
|
||||
member;
|
||||
member = member->next)
|
||||
{
|
||||
/* Skip over the all systems group entry */
|
||||
|
||||
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
|
||||
{
|
||||
/* REVISIT: Missing logic. No action is taken on the query. */
|
||||
|
||||
mld_check_querier(dev, ipv6, member, mrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!unspec && query->nsources == 0)
|
||||
if (query->nsources == 0)
|
||||
{
|
||||
ninfo("Multicast Address Specific Query\n");
|
||||
MLD_STATINCR(g_netstats.mld.mas_query_received);
|
||||
|
||||
/* We first need to re-lookup the group since we used the incoming
|
||||
* dest last time. Use the group address in the query.
|
||||
*/
|
||||
|
||||
group = mld_grpallocfind(dev, query->grpaddr);
|
||||
|
||||
/* REVISIT: Missing logic. No action is taken on the query. */
|
||||
|
||||
mld_check_querier(dev, ipv6, group, mrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Multicast Address and Source Specific Query\n");
|
||||
MLD_STATINCR(g_netstats.mld.massq_query_received);
|
||||
|
||||
/* We first need to re-lookup the group since we used the incoming
|
||||
* dest last time. Use the group address in the query.
|
||||
*/
|
||||
|
||||
group = mld_grpallocfind(dev, query->grpaddr);
|
||||
|
||||
/* REVISIT: Missing logic. No action is taken on the query. */
|
||||
|
||||
mld_check_querier(dev, ipv6, group, mrc);
|
||||
}
|
||||
|
||||
/* Send the report */
|
||||
|
||||
mld_send(dev, group, MLD_SEND_REPORT);
|
||||
}
|
||||
|
||||
/* Not sent to all systems -- Unicast query */
|
||||
/* Not sent to all systems. Check for Unicast General Query */
|
||||
|
||||
else if (!unspec)
|
||||
else if (net_ipv6addr_cmp(ipv6->destipaddr, dev->d_ipv6addr))
|
||||
{
|
||||
ninfo("Unicast query\n");
|
||||
MLD_STATINCR(g_netstats.mld.ucast_query_received);
|
||||
|
||||
mld_check_querier(dev, ipv6, group, mrc);
|
||||
/* Send the report */
|
||||
|
||||
mld_send(dev, group, MLD_SEND_REPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
nwarn("WARNING: Unhandled query\n");
|
||||
MLD_STATINCR(g_netstats.mld.bad_query_received);
|
||||
|
||||
/* Need to set d_len to zero to indication that nothing is being sent */
|
||||
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
|
|
@ -54,6 +54,69 @@
|
|||
|
||||
#define IPv6BUF ((FAR struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mld_report
|
||||
*
|
||||
* Description:
|
||||
* Common report handling. Since we are not a router, we do very little
|
||||
* on the receipt of a report from another member of the group.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mld_report(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
FAR struct mld_group_s *group;
|
||||
|
||||
/* Reports are send to the group multicast address. Hence, the IPv6
|
||||
* destipaddr idenfies the group.
|
||||
*/
|
||||
|
||||
ninfo("grpaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address.
|
||||
* If we are not a router (and I assume we are not), then can ignore
|
||||
* reports from groups that we are not a member of.
|
||||
*
|
||||
* REVISIT: Router support is not yet implemented.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MLD_ROUTER
|
||||
group = mld_grpallocfind(dev, ipv6->destipaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate group\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#else
|
||||
group = mld_grpfind(dev, ipv6->destipaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
nwarn("WARNING: Ignoring group. We are not a member\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* There are certainly other members of this group, we can clear the
|
||||
* LASTREPORT flag.
|
||||
*/
|
||||
|
||||
CLR_MLD_LASTREPORT(group->flags);
|
||||
|
||||
/* Need to set d_len to zero to indication that nothing is being sent */
|
||||
|
||||
dev->d_len = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -86,35 +149,10 @@
|
|||
int mld_report_v1(FAR struct net_driver_s *dev,
|
||||
FAR const struct mld_mcast_listen_report_v1_s *report)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
FAR struct mld_group_s *group;
|
||||
|
||||
ninfo("Version 1 Multicast Listener Report\n");
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
|
||||
MLD_STATINCR(g_netstats.mld.v1report_received);
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address */
|
||||
|
||||
group = mld_grpallocfind(dev, ipv6->destipaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate/find group\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* If we are a Querier, then reset the timer for that group. */
|
||||
|
||||
if (IS_MLD_QUERIER(group->flags))
|
||||
{
|
||||
mld_starttimer(group, MSEC2TICK(MLD_UNSOLREPORT_MSEC));
|
||||
CLR_MLD_LASTREPORT(group->flags);
|
||||
}
|
||||
|
||||
return OK;
|
||||
return mld_report(dev);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -136,51 +174,8 @@ int mld_report_v1(FAR struct net_driver_s *dev,
|
|||
int mld_report_v2(FAR struct net_driver_s *dev,
|
||||
FAR const struct mld_mcast_listen_report_v2_s *report)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
FAR struct mld_group_s *group;
|
||||
|
||||
ninfo("Version 2 Multicast Listener Report\n");
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
|
||||
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
|
||||
ipv6->destipaddr[6], ipv6->destipaddr[7]);
|
||||
|
||||
MLD_STATINCR(g_netstats.mld.v2report_received);
|
||||
|
||||
/* Check for a valid report
|
||||
*
|
||||
* REVISIT: Missing required test for Router Alert option. That has
|
||||
* already been handled in ipv6_input() but is not available here
|
||||
* unless we re-parse the extension options.
|
||||
*/
|
||||
|
||||
if (!net_is_addr_linklocal(ipv6->srcipaddr) || ipv6->ttl != 1)
|
||||
{
|
||||
nwarn("WARNING: Bad Report, ttl=%u\n", ipv6->ttl);
|
||||
nwarn(" srcipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
ipv6->srcipaddr[0], ipv6->srcipaddr[1], ipv6->srcipaddr[2],
|
||||
ipv6->srcipaddr[3], ipv6->srcipaddr[4], ipv6->srcipaddr[5],
|
||||
ipv6->srcipaddr[6], ipv6->srcipaddr[7]);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Find the group (or create a new one) using the incoming IP address */
|
||||
|
||||
group = mld_grpallocfind(dev, ipv6->destipaddr);
|
||||
if (group == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate/find group\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* If we are a Querier, then reset the timer for that group. */
|
||||
|
||||
if (IS_MLD_QUERIER(group->flags))
|
||||
{
|
||||
mld_starttimer(group, MSEC2TICK(MLD_UNSOLREPORT_MSEC));
|
||||
CLR_MLD_LASTREPORT(group->flags);
|
||||
}
|
||||
|
||||
return OK;
|
||||
return mld_report(dev);
|
||||
}
|
||||
|
|
|
@ -99,10 +99,10 @@
|
|||
* 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.
|
||||
* destipaddr - The IP address of the recipient of the message
|
||||
* 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
|
||||
|
@ -113,17 +113,13 @@
|
|||
****************************************************************************/
|
||||
|
||||
void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
||||
FAR const net_ipv6addr_t destipaddr)
|
||||
uint8_t msgtype)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6;
|
||||
FAR struct ipv6_router_alert_s *ra;
|
||||
FAR const uint16_t *destipaddr;
|
||||
unsigned int mldsize;
|
||||
|
||||
ninfo("msgtype: %02x \n", group->msgtype);
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
destipaddr[0], destipaddr[1], destipaddr[2], destipaddr[3],
|
||||
destipaddr[4], destipaddr[5], destipaddr[6], destipaddr[7]);
|
||||
|
||||
/* Select IPv6 */
|
||||
|
||||
IFF_SET_IPv6(dev->d_flags);
|
||||
|
@ -133,21 +129,25 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
* This will change.
|
||||
*/
|
||||
|
||||
switch (group->msgtype)
|
||||
switch (msgtype)
|
||||
{
|
||||
case MLD_SEND_GENQUERY: /* Send General Query */
|
||||
ninfo("Send General Query, flags=%02x\n", group->flags);
|
||||
mldsize = SIZEOF_MLD_MCAST_LISTEN_QUERY_S(0);
|
||||
break;
|
||||
|
||||
case MLD_SEND_REPORT: /* Send Unsolicited report */
|
||||
ninfo("Send Report, flags=%02x\n", group->flags);
|
||||
mldsize = sizeof(struct mld_mcast_listen_report_v1_s);
|
||||
break;
|
||||
|
||||
case MLD_SEND_DONE: /* Send Done message */
|
||||
ninfo("Send Done message, flags=%02x\n", group->flags);
|
||||
mldsize = sizeof(struct mld_mcast_listen_done_v1_s);
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("Bad msgtype: %02x \n", msgtype);
|
||||
DEBUGPANIC();
|
||||
return;
|
||||
}
|
||||
|
@ -174,7 +174,41 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
ipv6->proto = NEXT_HOPBYBOT_EH; /* Hop-to-hop extension header */
|
||||
ipv6->ttl = MLD_TTL; /* MLD Time-to-live */
|
||||
|
||||
/* Select the IPv6 source address (the local interface assigned to the
|
||||
* network device).
|
||||
*/
|
||||
|
||||
net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr);
|
||||
|
||||
/* Select the IPv6 destination address. This varies with the type of message
|
||||
* being sent:
|
||||
*
|
||||
* MESSAGE DESTINATION ADDRESS
|
||||
* General Query Message: The link-local, all nodes multicast address
|
||||
* MAS Query Messages: The group multicast address
|
||||
* Report Message: The group multicast address
|
||||
* Done Message: The link-local, all routers multicast address.
|
||||
*/
|
||||
|
||||
switch (msgtype)
|
||||
{
|
||||
case MLD_SEND_GENQUERY: /* Send General Query */
|
||||
destipaddr = g_ipv6_allnodes;
|
||||
break;
|
||||
|
||||
case MLD_SEND_REPORT: /* Send Unsolicited report */
|
||||
destipaddr = group->grpaddr;
|
||||
break;
|
||||
|
||||
case MLD_SEND_DONE: /* Send Done message */
|
||||
destipaddr = g_ipv6_allrouters;
|
||||
break;
|
||||
}
|
||||
|
||||
ninfo("destipaddr: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
destipaddr[0], destipaddr[1], destipaddr[2], destipaddr[3],
|
||||
destipaddr[4], destipaddr[5], destipaddr[6], destipaddr[7]);
|
||||
|
||||
net_ipv6addr_hdrcopy(ipv6->destipaddr, destipaddr);
|
||||
|
||||
/* Add the router alert IP header option.
|
||||
|
@ -194,7 +228,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
* router alert)
|
||||
*/
|
||||
|
||||
switch (group->msgtype)
|
||||
switch (msgtype)
|
||||
{
|
||||
case MLD_SEND_GENQUERY:
|
||||
{
|
||||
|
@ -236,6 +270,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
report->chksum = 0;
|
||||
report->chksum = ~icmpv6_chksum(dev);
|
||||
|
||||
SET_MLD_LASTREPORT(group->flags); /* Remember we were the last to report */
|
||||
MLD_STATINCR(g_netstats.mld.report_sent);
|
||||
}
|
||||
break;
|
||||
|
@ -258,14 +293,6 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
MLD_STATINCR(g_netstats.mld.done_sent);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Not yet supported */
|
||||
|
||||
case ICMPV6_MCAST_LISTEN_QUERY:
|
||||
case ICMPV6_MCAST_LISTEN_REPORT_V2:
|
||||
default:
|
||||
DEBUGPANIC();
|
||||
return;
|
||||
}
|
||||
|
||||
MLD_STATINCR(g_netstats.icmpv6.sent);
|
||||
|
|
|
@ -96,8 +96,7 @@
|
|||
* Timeout watchdog work
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from the wdog timer handler which runs in the
|
||||
* context of the timer interrupt handler.
|
||||
* This function is called from a work queue thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -196,7 +195,7 @@ static void mld_timeout(int argc, uint32_t arg, ...)
|
|||
group = (FAR struct mld_group_s *)arg;
|
||||
DEBUGASSERT(argc == 1 && group != NULL);
|
||||
|
||||
/* Perform the timeout-related operations on (preferably) the low prioirity
|
||||
/* Perform the timeout-related operations on (preferably) the low priority
|
||||
* work queue.
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in a new issue