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 Group Management Protocol (IGMP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_api.h"
29 #include "nx_igmp.h"
30
31 #ifndef NX_DISABLE_IPV4
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_igmp_multicast_interface_join_internal PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function handles the request to join the specified multicast */
45 /* group on a specified network device. */
46 /* */
47 /* INPUT */
48 /* */
49 /* ip_ptr IP instance pointer */
50 /* group_address Multicast group to join */
51 /* interface_index Index to the interface */
52 /* update_time Update time */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* tx_mutex_get Obtain protection mutex */
61 /* tx_mutex_put Release protection mutex */
62 /* (ip_link_driver) Associated IP link driver */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_nx_igmp_multicast_interface_join_internal(NX_IP * ip_ptr,ULONG group_address,UINT interface_index,UINT update_time)77 UINT _nx_igmp_multicast_interface_join_internal(NX_IP *ip_ptr, ULONG group_address,
78 UINT interface_index, UINT update_time)
79 {
80
81 UINT i;
82 UINT first_free;
83 NX_IP_DRIVER driver_request;
84 NX_INTERFACE *nx_interface;
85
86 /* If trace is enabled, insert this event into the trace buffer. */
87 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IGMP_MULTICAST_JOIN, ip_ptr, group_address, interface_index, 0, NX_TRACE_IGMP_EVENTS, 0, 0);
88
89 /* Obtain the IP mutex so we can search the multicast join list. */
90 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
91
92 nx_interface = &ip_ptr -> nx_ip_interface[interface_index];
93
94 /* Search the multicast join list for either the same group request. */
95 first_free = NX_MAX_MULTICAST_GROUPS;
96
97 for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
98 {
99
100 /* Determine if the specified entry is already in the multicast join list. */
101 if ((ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list == group_address) &&
102 (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list == nx_interface))
103 {
104
105 /* Yes, we have found the same entry. The only thing required in this
106 case is to increment the join count and return. */
107 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_count++;
108
109 /* Release the IP protection. */
110 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
111
112 /* Return success! */
113 return(NX_SUCCESS);
114 }
115
116 /* Check for an empty entry. */
117 if ((ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list == 0) &&
118 (first_free == NX_MAX_MULTICAST_GROUPS))
119 {
120
121 /* Remember the first free entry. */
122 first_free = i;
123 }
124 }
125
126 /* At this point, we have a new entry. First, check to see if there is an available
127 entry. */
128 if (first_free == NX_MAX_MULTICAST_GROUPS)
129 {
130
131 /* Release the protection of the IP instance. */
132 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
133
134 /* Return an error code to indicate there are no more group addresses
135 available. */
136 return(NX_NO_MORE_ENTRIES);
137 }
138
139 /* Register the new multicast group with the underlying driver to
140 ensure that there is room for the new group at the hardware level. */
141 driver_request.nx_ip_driver_ptr = ip_ptr;
142 driver_request.nx_ip_driver_command = NX_LINK_MULTICAST_JOIN;
143 driver_request.nx_ip_driver_physical_address_msw = NX_IP_MULTICAST_UPPER;
144 driver_request.nx_ip_driver_physical_address_lsw = NX_IP_MULTICAST_LOWER | (group_address & NX_IP_MULTICAST_MASK);
145 driver_request.nx_ip_driver_interface = nx_interface;
146
147 /* If trace is enabled, insert this event into the trace buffer. */
148 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_MULTICAST_JOIN, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
149
150 (nx_interface -> nx_interface_link_driver_entry)(&driver_request);
151
152 /* Check the return driver status. */
153 /*lint -e{644} suppress variable might not be initialized, since "nx_ip_driver_status" was initialized in nx_interface_link_driver_entry. */
154 if (driver_request.nx_ip_driver_status != NX_SUCCESS)
155 {
156
157 /* Release the protection of the IP instance. */
158 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
159
160 /* Return an error code to indicate there are no more group addresses
161 available. */
162 return(NX_NO_MORE_ENTRIES);
163 }
164
165 /* Set it up in the IP control structures. */
166 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_list = group_address;
167 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_interface_list = nx_interface;
168 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_count = 1;
169 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_update_time = update_time; /* Update on next IGMP periodic */
170 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_loopback_enable = ip_ptr -> nx_ip_igmp_global_loopback_enable;
171
172 #ifndef NX_DISABLE_IGMP_INFO
173 /* Increment the IGMP groups joined count. */
174 ip_ptr -> nx_ip_igmp_groups_joined++;
175 #endif
176
177 /* Release the protection over the IP instance. */
178 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
179
180 /* Return a successful status! */
181 return(NX_SUCCESS);
182 }
183 #endif /* !NX_DISABLE_IPV4 */
184
185