1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Internet Protocol (IPv6)                                            */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 #define NX_SOURCE_CODE
25 
26 
27 /* Include necessary system files.  */
28 #include "nx_api.h"
29 #include "nx_ipv6.h"
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _nxd_ipv6_multicast_interface_join                  PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Yuxin Zhou, Microsoft Corporation                                   */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This service allows an application to join a specific IPv6          */
44 /*    multicast address on a specific physical interface.  The link       */
45 /*    driver is notified to add the multicast address.                    */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    ip_ptr                                IP instance pointer           */
50 /*    group_address                         IPv6 multicast address        */
51 /*    interface_index                       Index to the phyical interface*/
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Completion status             */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    tx_mutex_get                          Obtain protection mutex       */
60 /*    tx_mutex_put                          Release protection mutex      */
61 /*    memset                                Clear the memory              */
62 /*    (ip_link_driver)                      Device driver entry point     */
63 /*    CHECK_IPV6_ADDRESSES_SAME             IPv6 address compare          */
64 /*    CHECK_UNSPECIFIED_ADDRESS             Check for :: address          */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    Application                                                         */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
75 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*                                                                        */
78 /**************************************************************************/
_nxd_ipv6_multicast_interface_join(NX_IP * ip_ptr,NXD_ADDRESS * group_address,UINT interface_index)79 UINT  _nxd_ipv6_multicast_interface_join(NX_IP *ip_ptr, NXD_ADDRESS *group_address, UINT interface_index)
80 {
81 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
82 
83 UINT          i;
84 UINT          first_free;
85 NX_IP_DRIVER  driver_request;
86 NX_INTERFACE *nx_interface;
87 
88     /* Obtain the IP mutex so we can search the multicast join list.  */
89     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
90 
91     nx_interface = &ip_ptr -> nx_ip_interface[interface_index];
92 
93     /* Search the multicast join list for either the same group request.  */
94     first_free =     NX_MAX_MULTICAST_GROUPS;
95 
96     for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
97     {
98 
99         /* Determine if the specified entry is already in the multicast join list.  */
100         if ((nx_interface == ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_interface_list) &&
101             (CHECK_IPV6_ADDRESSES_SAME(ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_list, group_address -> nxd_ip_address.v6)))
102         {
103 
104             /* Yes, we have found the same entry.  The only thing required in this
105                case is to increment the join count and return.  */
106             ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_count++;
107 
108             /* Release the IP protection.  */
109             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
110 
111             /* Return number of the group.  */
112             return(NX_SUCCESS);
113         }
114 
115         /* Check for an empty entry.  */
116         if (CHECK_UNSPECIFIED_ADDRESS(ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_list) && (first_free == NX_MAX_MULTICAST_GROUPS))
117         {
118 
119             /* Remember the first free entry.  */
120             first_free =  i;
121         }
122     }
123 
124     /* At this point, we have a new entry.   First, check to see if there is an available
125        entry.  */
126     if (first_free == NX_MAX_MULTICAST_GROUPS)
127     {
128 
129         /* Release the protection of the IP instance.  */
130         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
131 
132         /* Return an error code to indicate there are no more group addresses
133            available.  */
134         return(NX_NO_MORE_ENTRIES);
135     }
136 
137     /* Set it up in the IP control structures.  */
138     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_list[0]        =    group_address -> nxd_ip_address.v6[0];
139     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_list[1]        =    group_address -> nxd_ip_address.v6[1];
140     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_list[2]        =    group_address -> nxd_ip_address.v6[2];
141     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_list[3]        =    group_address -> nxd_ip_address.v6[3];
142     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_interface_list =    nx_interface;
143     ip_ptr -> nx_ipv6_multicast_entry[first_free].nx_ip_mld_join_count          =    1;
144 
145     /* Increment the MLD groups joined count.  */
146     ip_ptr -> nx_ipv6_multicast_groups_joined++;
147 
148     /* Register the new multicast group with the underlying driver to
149        ensure that there is room for the new group at the hardware level.  */
150     driver_request.nx_ip_driver_ptr                  =   ip_ptr;
151     driver_request.nx_ip_driver_command              =   NX_LINK_MULTICAST_JOIN;
152     driver_request.nx_ip_driver_physical_address_msw =   0x00003333;
153     driver_request.nx_ip_driver_physical_address_lsw =   group_address -> nxd_ip_address.v6[3];
154     driver_request.nx_ip_driver_interface            =   nx_interface;
155 
156     (nx_interface -> nx_interface_link_driver_entry)(&driver_request);
157 
158     /* Check the return driver status.   */
159     /*lint -e{644} suppress variable might not be initialized, since "nx_ip_driver_status" was initialized in nx_interface_link_driver_entry. */
160     if (driver_request.nx_ip_driver_status != NX_SUCCESS)
161     {
162 
163         /* Release the protection of the IP instance.  */
164         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
165 
166         /* Return an error code to indicate there are no more group addresses
167            available.  */
168         return(NX_OVERFLOW);
169     }
170 
171     /* Release the protection over the IP instance.  */
172     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
173 
174     /* Return SUCCESS.  */
175     return(NX_SUCCESS);
176 
177 #else
178     NX_PARAMETER_NOT_USED(ip_ptr);
179     NX_PARAMETER_NOT_USED(group_address);
180     NX_PARAMETER_NOT_USED(interface_index);
181 
182     return(NX_NOT_SUPPORTED);
183 
184 #endif /* NX_ENABLE_IPV6_MULTICAST && FEATURE_NX_IPV6 */
185 }
186 
187