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