1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: File where the function for processing multicast-to-unicast conversion is stored.
15 * Create: 2021-12-15
16 */
17 /*****************************************************************************
18 1 头文件包含
19 *****************************************************************************/
20 #include "hmac_m2u.h"
21
22 #include "oam_struct.h"
23 #include "hmac_tx_data.h"
24 #include "hmac_tx_encap.h"
25
26 #ifdef _PRE_WLAN_FEATURE_VIRTUAL_MULTI_STA
27 #include "hmac_wds.h"
28 #endif
29 #include "hmac_feature_dft.h"
30 #include "frw_hmac.h"
31 #include "hmac_feature_interface.h"
32
33 #ifdef __cplusplus
34 #if __cplusplus
35 extern "C" {
36 #endif
37 #endif
38
39 #undef THIS_FILE_ID
40 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_M2U_C
41
42 #undef THIS_MOD_ID
43 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
44
45 #ifndef IPPROTO_IGMP
46 #define IPPROTO_IGMP 2
47 #endif
48 /*****************************************************************************
49 3 函数实现
50 *****************************************************************************/
51
is_igmp_report_leave_packet(const osal_u8 type)52 static INLINE__ osal_u8 is_igmp_report_leave_packet(const osal_u8 type)
53 {
54 return (type == MAC_IGMPV1_REPORT_TYPE) || (type == MAC_IGMPV2_REPORT_TYPE) ||
55 (type == MAC_IGMPV2_LEAVE_TYPE) || (type == MAC_IGMPV3_REPORT_TYPE);
56 }
57
58 /* Is packet type is either leave or report */
is_igmpv3_mode(const osal_u8 type)59 static INLINE__ osal_u8 is_igmpv3_mode(const osal_u8 type)
60 {
61 return (type == IGMPV3_MODE_IS_INCLUDE) || (type == IGMPV3_MODE_IS_EXCLUDE) ||
62 (type == IGMPV3_CHANGE_TO_INCLUDE) || (type == IGMPV3_CHANGE_TO_EXCLUDE) ||
63 (type == IGMPV3_ALLOW_NEW_SOURCES) || (type == IGMPV3_BLOCK_OLD_SOURCES);
64 }
65
66 /* Is packet type is either leave or report */
is_mld_report_leave_packet(const osal_u8 type)67 static INLINE__ osal_u8 is_mld_report_leave_packet(const osal_u8 type)
68 {
69 return (type == MLDV1_REPORT_TYPE) || (type == MLDV1_DONE_TYPE) || (type == MLDV2_REPORT_TYPE);
70 }
71
is_mldv2_mode(const osal_u8 type)72 static INLINE__ osal_u8 is_mldv2_mode(const osal_u8 type)
73 {
74 return (type == MLDV2_MODE_IS_INCLUDE) || (type == MLDV2_MODE_IS_EXCLUDE) ||
75 (type == MLDV2_CHANGE_TO_INCLUDE) || (type == MLDV2_CHANGE_TO_EXCLUDE) ||
76 (type == MLDV2_ALLOW_NEW_SOURCES) || (type == MLDV2_BLOCK_OLD_SOURCES);
77 }
78
oal_is_icmpv6_proto(osal_u16 ether_data_type,const osal_u8 * ip_head)79 static INLINE__ osal_bool oal_is_icmpv6_proto(osal_u16 ether_data_type, const osal_u8 *ip_head)
80 {
81 return (((ether_data_type) == oal_host2net_short(ETHER_TYPE_IPV6)) &&
82 (((osal_u8)(ip_head[6]) == 0x3a) || ((osal_u8)(ip_head[40]) == 0x3a))); /* 6 40:数组下标 */
83 }
84
oal_is_igmp_proto(osal_u16 ether_data_type,const osal_u8 * ip_head)85 static INLINE__ osal_bool oal_is_igmp_proto(osal_u16 ether_data_type, const osal_u8 *ip_head)
86 {
87 /* 9:数组下标 */
88 return ((ether_data_type == oal_host2net_short(ETHER_TYPE_IP)) && ((osal_u8)((ip_head)[9]) == 0x02));
89 }
90
igmpv3_grp_rec_len(const mac_igmp_v3_grec_stru * grec)91 static INLINE__ osal_u32 igmpv3_grp_rec_len(const mac_igmp_v3_grec_stru *grec)
92 {
93 return (osal_u32)(8 + (((osal_u16)(grec->grec_nsrcs + grec->grec_auxwords)) << 2)); /* 8:基本偏移量 2: 左移位数 */
94 }
95
oal_ipv4_is_multicast(const osal_u8 * daddr)96 static INLINE__ osal_bool oal_ipv4_is_multicast(const osal_u8 *daddr)
97 {
98 return ((osal_u8)(daddr[0]) >= 224 && ((osal_u8)(daddr[0]) <= 239)); /* IPv4多播范围: 224.0.0.0--239.255.255.255 */
99 }
100
101 /*****************************************************************************
102 函 数 名 : hmac_m2u_add_member_list
103 功能描述 : 将一个组成员加入到相对应的组中去
104 输入参数 : grp_list 组播组结构体; list_entry 待更新节点结构体
105 输出参数 : ul_ret
106 *****************************************************************************/
hmac_m2u_add_member_list(hmac_m2u_grp_list_entry_stru * grp_list,hmac_m2u_list_update_stru * list_entry)107 OAL_STATIC osal_u32 hmac_m2u_add_member_list(hmac_m2u_grp_list_entry_stru *grp_list,
108 hmac_m2u_list_update_stru *list_entry)
109 {
110 hmac_m2u_grp_member_stru *grp_member;
111 hmac_m2u_stru *m2u_struct = (hmac_m2u_stru *)list_entry->hmac_vap->m2u;
112 osal_u32 ul_ret = OAL_SUCC;
113
114 if ((grp_list->sta_num >= MAX_STA_NUM_OF_ONE_GROUP) ||
115 (m2u_struct->m2u_snooplist.total_sta_num >= MAX_STA_NUM_OF_ALL_GROUP)) {
116 oam_warning_log3(0, OAM_SF_M2U,
117 "vap_id[%d] {hmac_m2u_add_member_list::sta num out of limit!current total_sta_num:[%d] ,sta_num:[%d].}",
118 list_entry->hmac_vap->vap_id,
119 m2u_struct->m2u_snooplist.total_sta_num, grp_list->sta_num);
120 return OAL_ERR_CODE_ARRAY_OVERFLOW;
121 }
122
123 grp_member = (hmac_m2u_grp_member_stru *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL,
124 OAL_SIZEOF(hmac_m2u_grp_member_stru), OAL_TRUE);
125 if (osal_unlikely(grp_member == OAL_PTR_NULL)) {
126 oam_error_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_add_member_list:: oal_mem_alloc failed!!}",
127 list_entry->hmac_vap->vap_id);
128 return OAL_ERR_CODE_PTR_NULL;
129 }
130
131 memset_s(grp_member, OAL_SIZEOF(hmac_m2u_grp_member_stru), 0x0, OAL_SIZEOF(hmac_m2u_grp_member_stru));
132 osal_list_add_tail(&(grp_member->member_entry), &(grp_list->src_list)); // 插入节点
133 if (memcpy_s(grp_member->src_ip_addr, sizeof(grp_member->src_ip_addr), list_entry->src_ip_addr,
134 sizeof(list_entry->src_ip_addr)) != EOK) {
135 oam_error_log0(0, OAM_SF_M2U, "{hmac_m2u_add_member_list::memcpy_s ip error}");
136 }
137 oal_set_mac_addr(grp_member->grp_member_mac, list_entry->new_member_mac);
138
139 grp_member->hmac_user = list_entry->hmac_user;
140 grp_member->mode = list_entry->cmd;
141 grp_member->timestamp = list_entry->timestamp;
142 grp_member->src_ip_addr_len = list_entry->src_ip_addr_len;
143 grp_list->sta_num++;
144 m2u_struct->m2u_snooplist.total_sta_num++;
145
146 oam_warning_log3(0, OAM_SF_M2U,
147 "vap_id[%d] {hmac_m2u_add_member_list::add one sta !current total_sta_num:[%d] ,sta_num:[%d].}",
148 list_entry->hmac_vap->vap_id,
149 m2u_struct->m2u_snooplist.total_sta_num, grp_list->sta_num);
150 return ul_ret;
151 }
152
153 /*****************************************************************************
154 函 数 名 : hmac_m2u_remove_expired_member
155 功能描述 : 删除某个组内超时的组成员
156 输入参数 : grp_list 组播组结构体; hmac_vap vap 结构体; nowtimestamp nowtime变量
157 输出参数 : 无
158 *****************************************************************************/
hmac_m2u_remove_expired_member(hmac_m2u_grp_list_entry_stru * grp_list,hmac_vap_stru * hmac_vap,osal_u32 nowtimestamp)159 OAL_STATIC osal_u32 hmac_m2u_remove_expired_member(hmac_m2u_grp_list_entry_stru *grp_list,
160 hmac_vap_stru *hmac_vap, osal_u32 nowtimestamp)
161 {
162 hmac_m2u_grp_member_stru *grp_member;
163 struct osal_list_head *grp_member_entry;
164 struct osal_list_head *member_entry_temp;
165 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
166 osal_u32 ul_ret = OAL_SUCC;
167
168 if (m2u == OAL_PTR_NULL) {
169 return OAL_FAIL;
170 }
171
172 /* 遍历一个组,每次取出组中成员,超时则删除该成员 */
173 osal_list_for_each_safe(grp_member_entry, member_entry_temp, &(grp_list->src_list)) {
174 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
175 hmac_m2u_grp_member_stru, member_entry);
176 if (oal_time_get_runtime((grp_member->timestamp), nowtimestamp) > (m2u->timeout)) {
177 osal_list_del(&(grp_member->member_entry));
178 oal_mem_free(grp_member, OAL_TRUE);
179
180 oam_warning_log3(0, OAM_SF_M2U,
181 "vap_id[%d] {hmac_m2u_remove_expired_member:: current total sta num:[%d],sta num:[%d]}",
182 hmac_vap->vap_id,
183 m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
184
185 grp_list->sta_num--;
186 m2u->m2u_snooplist.total_sta_num--;
187
188 oam_warning_log3(0, OAM_SF_M2U,
189 "vap_id[%d] {hmac_m2u_remove_expired_member::remove one sta. current total sta num:[%d],sta num:[%d]}",
190 hmac_vap->vap_id,
191 m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
192 }
193 }
194 return ul_ret;
195 }
196
197 /*****************************************************************************
198 函 数 名 : hmac_m2u_remove_one_member
199 功能描述 : 从一个给定的组播组下,删除某个组播组成员
200 输入参数 : grp_list 组播组结构体; grp_member_addr 组播成员IP地址
201 输出参数 : 无
202 *****************************************************************************/
hmac_m2u_remove_one_member(hmac_m2u_grp_list_entry_stru * grp_list,hmac_vap_stru * hmac_vap,osal_u8 * grp_member_addr)203 OAL_STATIC osal_void hmac_m2u_remove_one_member(hmac_m2u_grp_list_entry_stru *grp_list,
204 hmac_vap_stru *hmac_vap, osal_u8 *grp_member_addr)
205 {
206 hmac_m2u_grp_member_stru *grp_member;
207 struct osal_list_head *grp_member_entry;
208 struct osal_list_head *member_entry_temp;
209 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
210
211 if (m2u == OAL_PTR_NULL) {
212 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_remove_one_member::m2u is null}",
213 hmac_vap->vap_id);
214 return;
215 }
216
217 /* 遍历一个组播组删除指定成员 */
218 osal_list_for_each_safe(grp_member_entry, member_entry_temp, &(grp_list->src_list)) {
219 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
220 hmac_m2u_grp_member_stru, member_entry);
221 if (oal_compare_mac_addr(grp_member_addr, grp_member->grp_member_mac) == 0) {
222 osal_list_del(&(grp_member->member_entry));
223 oal_mem_free(grp_member, OAL_TRUE);
224
225 oam_warning_log4(0, OAM_SF_M2U,
226 "vap_id[%d] {hmac_m2u_remove_one_member::current sta_num:%d total_sta_num:%d group_num:%d}",
227 hmac_vap->vap_id, grp_list->sta_num,
228 m2u->m2u_snooplist.total_sta_num, m2u->m2u_snooplist.group_list_count);
229
230 grp_list->sta_num--;
231 m2u->m2u_snooplist.total_sta_num--;
232
233 oam_warning_log4(0, OAM_SF_M2U,
234 "{hmac_m2u_remove_one_member::remove one sta from group:0x%02x 0x%02x 0x%02x 0x%02x 0xxx 0xxx!}",
235 /* 0,1,2表示组播组的MAC地址位 */
236 grp_list->group_mac[0], grp_list->group_mac[1], grp_list->group_mac[2],
237 grp_list->group_mac[3]); /* 3表示组播组的MAC地址位 */
238 oam_warning_log4(0, OAM_SF_M2U,
239 "vap_id[%d] {hmac_m2u_remove_one_member::current sta_num:%d total_sta_num:%d group_num:%d}",
240 hmac_vap->vap_id, grp_list->sta_num,
241 m2u->m2u_snooplist.total_sta_num, m2u->m2u_snooplist.group_list_count);
242 }
243 }
244 }
245
246 /*****************************************************************************
247 函 数 名 : hmac_m2u_find_member_src
248 功能描述 : 根据成员的mac地址以及组播源地址返回所需的组成员
249 输入参数 : grp_list 组播组结构体; grp_member_addr 组播成员IP地址; src_ip_addr 组播源IP地址
250 输出参数 : grp_member 组播组成员结构体 OR 空指针
251 *****************************************************************************/
hmac_m2u_find_member_src(hmac_m2u_grp_list_entry_stru * grp_list,osal_u8 * grp_member_addr,osal_u8 * src_ip_addr)252 OAL_STATIC hmac_m2u_grp_member_stru *hmac_m2u_find_member_src(hmac_m2u_grp_list_entry_stru *grp_list,
253 osal_u8 *grp_member_addr, osal_u8 *src_ip_addr)
254 {
255 hmac_m2u_grp_member_stru *grp_member;
256 struct osal_list_head *grp_member_entry;
257
258 /* 遍历一个组播组,找到该组中src ip匹配的成员 */
259 osal_list_for_each(grp_member_entry, &(grp_list->src_list)) {
260 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
261 hmac_m2u_grp_member_stru, member_entry);
262 if ((oal_compare_mac_addr(grp_member_addr, grp_member->grp_member_mac) == 0) &&
263 (osal_memcmp(src_ip_addr, grp_member->src_ip_addr, grp_member->src_ip_addr_len) == 0)) {
264 return grp_member;
265 }
266 }
267 return OAL_PTR_NULL;
268 }
269
270 /*****************************************************************************
271 函 数 名 : hmac_m2u_find_member
272 功能描述 : 根据成员的mac地址返回所需的组成员
273 输入参数 : grp_list 组播组结构体; grp_member_addr 组播组成员IP地址
274 输出参数 : grp_member 组播组成员结构体 OR 空指针
275 *****************************************************************************/
hmac_m2u_find_member(hmac_m2u_grp_list_entry_stru * grp_list,osal_u8 * grp_member_addr)276 OAL_STATIC hmac_m2u_grp_member_stru *hmac_m2u_find_member(hmac_m2u_grp_list_entry_stru *grp_list,
277 osal_u8 *grp_member_addr)
278 {
279 hmac_m2u_grp_member_stru *grp_member;
280 struct osal_list_head *grp_member_entry;
281
282 /* 遍历一个组播组,找到该组中地址匹配的成员 */
283 osal_list_for_each(grp_member_entry, &(grp_list->src_list)) {
284 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
285 hmac_m2u_grp_member_stru, member_entry);
286 if (oal_compare_mac_addr(grp_member_addr, grp_member->grp_member_mac) == 0) {
287 return grp_member;
288 }
289 }
290
291 return OAL_PTR_NULL;
292 }
293
294 /*****************************************************************************
295 函 数 名 : hmac_m2u_find_group_list
296 功能描述 : 根据组的mac地址返回所需的组
297 输入参数 : hmac_vap vap结构体; hmac_m2u_list_update_stru *list_entry待查找组播组信息
298 输出参数 : grp_list_member 组播组结构体 OR 空指针
299 *****************************************************************************/
hmac_m2u_find_group_list(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry)300 OAL_STATIC hmac_m2u_grp_list_entry_stru *hmac_m2u_find_group_list(hmac_vap_stru *hmac_vap,
301 hmac_m2u_list_update_stru *list_entry)
302 {
303 hmac_m2u_snoop_list_stru *snp_list;
304 hmac_m2u_grp_list_entry_stru *grp_list_member;
305 struct osal_list_head *grp_list_entry;
306 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
307
308 if (m2u == OAL_PTR_NULL) {
309 return OAL_PTR_NULL;
310 }
311
312 snp_list = &(m2u->m2u_snooplist);
313
314 /* 遍历组播组链表,找到地址匹配的组播组 */
315 osal_list_for_each(grp_list_entry, &(snp_list->grp_list)) {
316 grp_list_member = (hmac_m2u_grp_list_entry_stru *)osal_list_entry(grp_list_entry,
317 hmac_m2u_grp_list_entry_stru, grp_entry);
318 if ((oal_compare_mac_addr(list_entry->grp_mac, grp_list_member->group_mac) == 0) &&
319 (osal_memcmp(&(list_entry->outer_vlan_tag), &(grp_list_member->outer_vlan_tag),
320 OAL_SIZEOF(mac_vlan_tag_stru)) == 0)) {
321 return grp_list_member;
322 }
323 }
324
325 return OAL_PTR_NULL;
326 }
327
328 /*****************************************************************************
329 函 数 名 : hmac_m2u_create_grp_list
330 功能描述 : 根据组播组的MAC地址创建一个组,如果此组存在则返回该组,否则重新创建
331 输入参数 : hmac_vap vap结构体; hmac_m2u_list_update_stru *list_entry,待 操作节点信息
332 输出参数 : grp_list_member 组播组结构体
333 *****************************************************************************/
hmac_m2u_create_grp_list(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry)334 OAL_STATIC hmac_m2u_grp_list_entry_stru *hmac_m2u_create_grp_list(hmac_vap_stru *hmac_vap,
335 hmac_m2u_list_update_stru *list_entry)
336 {
337 hmac_m2u_snoop_list_stru *snp_list;
338 hmac_m2u_grp_list_entry_stru *grp_list_member = OAL_PTR_NULL;
339 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
340
341 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
342 return grp_list_member;
343 }
344
345 snp_list = &(m2u->m2u_snooplist);
346 grp_list_member = hmac_m2u_find_group_list(hmac_vap, list_entry);
347 if (grp_list_member == OAL_PTR_NULL) {
348 if (snp_list->group_list_count >= MAX_NUM_OF_GROUP) {
349 oam_warning_log2(0, OAM_SF_M2U,
350 "vap_id[%d] {hmac_m2u_create_grp_list::snp_list->group_list_count is[%d].}",
351 hmac_vap->vap_id, snp_list->group_list_count);
352 return OAL_PTR_NULL;
353 }
354 grp_list_member = (hmac_m2u_grp_list_entry_stru *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL,
355 OAL_SIZEOF(hmac_m2u_grp_list_entry_stru), OAL_TRUE);
356 if (osal_unlikely(grp_list_member == OAL_PTR_NULL)) {
357 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_create_grp_list::grp_list_member null.}",
358 hmac_vap->vap_id);
359 return grp_list_member;
360 }
361 memset_s(grp_list_member, OAL_SIZEOF(hmac_m2u_grp_list_entry_stru), 0x0,
362 OAL_SIZEOF(hmac_m2u_grp_list_entry_stru));
363 if (memcpy_s(&(grp_list_member->outer_vlan_tag), OAL_SIZEOF(grp_list_member->outer_vlan_tag),
364 &(list_entry->outer_vlan_tag), OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) {
365 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_create_grp_list::memcpy vlan fail", hmac_vap->vap_id);
366 }
367 osal_list_add_tail(&(grp_list_member->grp_entry), &(snp_list->grp_list));
368 oal_set_mac_addr(grp_list_member->group_mac, list_entry->grp_mac);
369 OSAL_INIT_LIST_HEAD(&(grp_list_member->src_list));
370 snp_list->group_list_count++;
371
372 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_create_grp_list::create a new group.group num:[%d]}",
373 hmac_vap->vap_id, snp_list->group_list_count);
374 }
375 return grp_list_member;
376 }
377
378 /*
379 * 功能描述: 更新的报文中有组播源的场景
380 */
hmac_m2u_update_snoop_list_with_multicast_source(hmac_m2u_grp_list_entry_stru * grp_list,hmac_m2u_list_update_stru * list_entry)381 OAL_STATIC osal_u32 hmac_m2u_update_snoop_list_with_multicast_source(hmac_m2u_grp_list_entry_stru *grp_list,
382 hmac_m2u_list_update_stru *list_entry)
383 {
384 hmac_m2u_grp_member_stru *grp_member_list = OSAL_NULL;
385 osal_u32 ret = OAL_SUCC;
386
387 oam_info_log3(0, OAM_SF_M2U,
388 "{hmac_m2u_update_snoop_list::list_entry is assigned src_ip_addr the first 4 byte[%02x][%02x][%02x][xx]}",
389 /* 0,1,2表示组播源节点的MAC地址位 */
390 list_entry->src_ip_addr[0], list_entry->src_ip_addr[1], list_entry->src_ip_addr[2]);
391 grp_member_list = hmac_m2u_find_member_src(grp_list, list_entry->new_member_mac,
392 list_entry->src_ip_addr);
393 if (grp_member_list != OAL_PTR_NULL) {
394 grp_member_list->mode = list_entry->cmd;
395 grp_member_list->timestamp = list_entry->timestamp; // 有组播源时更新时间戳
396 } else {
397 ret = hmac_m2u_add_member_list(grp_list, list_entry);
398 }
399
400 return ret;
401 }
402
403 /*
404 * 功能描述: 更新的报文中没有组播源的场景
405 */
hmac_m2u_update_snoop_list_without_multicast_source(hmac_m2u_grp_list_entry_stru * grp_list,hmac_m2u_list_update_stru * list_entry)406 OAL_STATIC osal_u32 hmac_m2u_update_snoop_list_without_multicast_source(hmac_m2u_grp_list_entry_stru *grp_list,
407 hmac_m2u_list_update_stru *list_entry)
408 {
409 hmac_m2u_grp_member_stru *grp_member_list = OSAL_NULL;
410 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(list_entry->hmac_vap->m2u);
411 osal_u32 ret = OAL_SUCC;
412
413 grp_member_list = hmac_m2u_find_member(grp_list, list_entry->new_member_mac);
414 if (grp_member_list != OAL_PTR_NULL) {
415 /* 存在该节点,并且该组中的该节点的有指定的组播源,清空组中的所有该节点,如果更新节点的cmd为INC 再add */
416 if (!OAL_IPV6_IS_UNSPECIFIED_ADDR(grp_member_list->src_ip_addr)) {
417 hmac_m2u_remove_one_member(grp_list, list_entry->hmac_vap,
418 list_entry->new_member_mac);
419 if (grp_member_list->mode == HMAC_M2U_CMD_INCLUDE_LIST) {
420 oam_info_log2(0, OAM_SF_M2U,
421 "vap_id[%d] {hmac_m2u_update_snoop_list::grp_member_list->mode is [%d].}",
422 list_entry->hmac_vap->vap_id, grp_member_list->mode);
423 ret = hmac_m2u_add_member_list(grp_list, list_entry);
424 }
425 } else if (list_entry->cmd == HMAC_M2U_CMD_EXCLUDE_LIST) {
426 /* 原组中的该节点未指定组播源,如果待更新节点的CMD为EXC,则删除原组播组中的该节点 */
427 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_update_snoop_list::list_entry->cmd is [%d].}",
428 list_entry->hmac_vap->vap_id, list_entry->cmd);
429 osal_list_del(&(grp_member_list->member_entry));
430 oal_mem_free(grp_member_list, OAL_TRUE);
431
432 oam_warning_log3(0, OAM_SF_M2U,
433 "vap_id[%d]{hmac_m2u_update_snoop_list::current total_sta_num:[%d] ,sta_num:[%d]}",
434 list_entry->hmac_vap->vap_id,
435 m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
436
437 grp_list->sta_num--;
438 m2u->m2u_snooplist.total_sta_num--;
439
440 oam_warning_log3(0, OAM_SF_M2U,
441 "vap_id[%d] {hmac_m2u_update_snoop_list::remove one sta. current total_sta_num:[%d] ,sta_num:[%d]}",
442 list_entry->hmac_vap->vap_id,
443 m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
444 }
445 } else if (list_entry->cmd != HMAC_M2U_CMD_EXCLUDE_LIST) {
446 /* 特定组中不存在该节点,并且更新节点的CMD不为EXC则ADD */
447 oam_info_log2(0, OAM_SF_M2U,
448 "vap_id[%d] {hmac_m2u_update_snoop_list:grp_member_list == NULL && list_entry->cmd is [%d]}",
449 list_entry->hmac_vap->vap_id, list_entry->cmd);
450 ret = hmac_m2u_add_member_list(grp_list, list_entry);
451 }
452
453 return ret;
454 }
455
456 /*****************************************************************************
457 函 数 名 : hmac_m2u_Update_Snoop_List
458 功能描述 : 根据接收到的用户信息更新链表
459 输入参数 : list_entry 待更新节点结构体
460 *****************************************************************************/
hmac_m2u_update_snoop_list(hmac_m2u_list_update_stru * list_entry)461 osal_u32 hmac_m2u_update_snoop_list(hmac_m2u_list_update_stru *list_entry)
462 {
463 hmac_m2u_grp_list_entry_stru *grp_list;
464
465 list_entry->timestamp = (osal_u32)oal_time_get_stamp_ms();
466 grp_list = hmac_m2u_find_group_list(list_entry->hmac_vap, list_entry);
467 if (grp_list == OAL_PTR_NULL) {
468 if (list_entry->cmd == HMAC_M2U_CMD_EXCLUDE_LIST) {
469 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_update_snoop_list::find_grp_list null.}",
470 list_entry->hmac_vap->vap_id);
471 return OAL_ERR_CODE_PTR_NULL;
472 } else {
473 grp_list = hmac_m2u_create_grp_list(list_entry->hmac_vap, list_entry);
474 if (osal_unlikely(grp_list == OAL_PTR_NULL)) {
475 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_update_snoop_list::create_grp_list null.}",
476 list_entry->hmac_vap->vap_id);
477 return OAL_ERR_CODE_PTR_NULL;
478 }
479 }
480 }
481
482 if (!OAL_IPV6_IS_UNSPECIFIED_ADDR(list_entry->src_ip_addr)) {
483 /* 更新信息中有组播源,如果链表中存在指定该组播源的该节点,则更新该节点的状态,否则重新创建加入链表 */
484 return hmac_m2u_update_snoop_list_with_multicast_source(grp_list, list_entry);
485 } else {
486 /* 更新信息中没有组播源 */
487 return hmac_m2u_update_snoop_list_without_multicast_source(grp_list, list_entry);
488 }
489 }
490
491 /*****************************************************************************
492 函 数 名 : hmac_m2u_show_snoop_deny_table
493 功能描述 : 打印黑名单
494 输入参数 : hmac_vap vap结构体
495 *****************************************************************************/
hmac_m2u_show_snoop_deny_table(hmac_vap_stru * hmac_vap)496 osal_void hmac_m2u_show_snoop_deny_table(hmac_vap_stru *hmac_vap)
497 {
498 hmac_m2u_stru *m2u;
499 osal_u8 idx;
500 hmac_m2u_snoop_list_stru *snp_list;
501
502 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
503 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_show_snoop_deny_table::hmac_vap is null}");
504 return;
505 }
506
507 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
508
509 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
510 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_show_snoop_deny_table::m2u is null}",
511 hmac_vap->vap_id);
512 return;
513 }
514
515 snp_list = &(m2u->m2u_snooplist);
516
517 if ((snp_list->deny_count_ipv4 == 0) && (snp_list->deny_count_ipv6 == 0)) {
518 return;
519 }
520 for (idx = 0; idx < snp_list->deny_count_ipv4; idx++) {
521 /* 打印黑名单的IPv4地址 */
522 char temp[MAX_STR_SIZE_OF_U8]; // 最多3个字符 + 1个'\0' = 4
523 int len = snprintf_s(temp, MAX_STR_SIZE_OF_U8, MAX_STR_SIZE_OF_U8 - 1,
524 "%u", ((snp_list->deny_group[idx]) & 0xff)); // itoa得到字符串
525 if (len >= 0) {
526 (osal_void)memset_s(temp, sizeof(temp), 'x', (size_t)len); // 隐私保护处理,用'x'掩去
527 oam_warning_log3(0, OAM_SF_M2U, "{hmac_m2u_show_snoop_deny_table:: deny addr_ipv4 = %d.%d.%d.x}",
528 (osal_u32)((snp_list->deny_group[idx] >> 24) & 0xff), /* 24表示黑名单按右偏移取值 */
529 (osal_u32)((snp_list->deny_group[idx] >> 16) & 0xff), /* 16表示黑名单按右偏移取值 */
530 (osal_u32)((snp_list->deny_group[idx] >> 8) & 0xff)); /* 8表示黑名单按右偏移取值 */
531 }
532 }
533 for (idx = 0; idx < snp_list->deny_count_ipv6; idx++) {
534 /* 打印黑名单的IPv6地址 */
535 oam_warning_log1(0, OAM_SF_M2U,
536 "{hmac_m2u_show_snoop_deny_table:: deny addr_ipv6 = [%08x][xxxxxxxx][xxxxxxxx][xxxxxxxx]}",
537 oal_host2net_long(*(osal_u32*)(&snp_list->deny_group_ipv6[idx][0])));
538 }
539 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
540 }
541
542 /*****************************************************************************
543 函 数 名 : hmac_m2u_snoop_is_denied
544 功能描述 : 所加入组播组的IP地址是否在黑名单内
545 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IP地址
546 输出参数 : OAL_FALSE OR OAL_TRUE
547 *****************************************************************************/
hmac_m2u_snoop_is_denied_ipv4(hmac_vap_stru * hmac_vap,osal_u32 grpaddr)548 OAL_STATIC osal_u32 hmac_m2u_snoop_is_denied_ipv4(hmac_vap_stru *hmac_vap, osal_u32 grpaddr)
549 {
550 osal_u8 idx;
551 hmac_m2u_snoop_list_stru *snp_list;
552 hmac_m2u_stru *m2u;
553
554 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
555 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_snoop_is_denied_ipv4::hmac_vap is null}");
556 return OAL_ERR_CODE_PTR_NULL;
557 }
558
559 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
560
561 if (m2u == OAL_PTR_NULL) {
562 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_snoop_is_denied_ipv4::m2u is null}",
563 hmac_vap->vap_id);
564 return OAL_ERR_CODE_PTR_NULL;
565 }
566
567 snp_list = &(m2u->m2u_snooplist);
568
569 if (snp_list->deny_count_ipv4 == 0) {
570 return OAL_FALSE;
571 }
572 for (idx = 0; idx < snp_list->deny_count_ipv4; idx++) {
573 if (grpaddr != snp_list->deny_group[idx]) {
574 continue;
575 }
576 return OAL_TRUE;
577 }
578 return OAL_FALSE;
579 }
580
581 /*****************************************************************************
582 函 数 名 : hmac_m2u_snoop_is_denied_ipv6
583 功能描述 : 所加入组播组的IPv6地址是否在黑名单内
584 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IPv6地址
585 输出参数 : OAL_FALSE OR OAL_TRUE
586 *****************************************************************************/
hmac_m2u_snoop_is_denied_ipv6(hmac_vap_stru * hmac_vap,osal_u8 * grpaddr)587 OAL_STATIC osal_u32 hmac_m2u_snoop_is_denied_ipv6(hmac_vap_stru *hmac_vap, osal_u8 *grpaddr)
588 {
589 osal_u8 idx;
590 hmac_m2u_snoop_list_stru *snp_list;
591 hmac_m2u_stru *m2u;
592
593 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
594 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_snoop_is_denied_ipv6::hmac_vap is null}");
595 return OAL_ERR_CODE_PTR_NULL;
596 }
597
598 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
599
600 if (m2u == OAL_PTR_NULL) {
601 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_snoop_is_denied_ipv6::m2u is null}",
602 hmac_vap->vap_id);
603 return OAL_ERR_CODE_PTR_NULL;
604 }
605
606 snp_list = &(m2u->m2u_snooplist);
607 if (snp_list->deny_count_ipv6 == 0) {
608 return OAL_FALSE;
609 }
610 for (idx = 0; idx < snp_list->deny_count_ipv6; idx++) {
611 if (osal_memcmp(grpaddr, snp_list->deny_group_ipv6[idx], OAL_IPV6_ADDR_SIZE) == 0) {
612 return OAL_TRUE;
613 }
614 }
615 return OAL_FALSE;
616 }
617 /*****************************************************************************
618 函 数 名 : hmac_m2u_clear_deny_table
619 功能描述 : 清空黑名单
620 输入参数 : hmac_vap vap结构体
621 输出参数 : 无
622 *****************************************************************************/
hmac_m2u_clear_deny_table(hmac_vap_stru * hmac_vap)623 osal_void hmac_m2u_clear_deny_table(hmac_vap_stru *hmac_vap)
624 {
625 hmac_m2u_snoop_list_stru *snp_list;
626 hmac_m2u_stru *m2u;
627
628 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
629 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_clear_deny_table::hmac_vap is null}");
630 return;
631 }
632
633 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
634
635 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
636 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_clear_deny_table::m2u is null}",
637 hmac_vap->vap_id);
638 return;
639 }
640
641 snp_list = &(m2u->m2u_snooplist);
642 snp_list->deny_count_ipv4 = DEFAULT_IPV4_DENY_GROUP_COUNT;
643 snp_list->deny_count_ipv6 = DEFAULT_IPV6_DENY_GROUP_COUNT;
644 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
645 return;
646 }
647
648 /*****************************************************************************
649 功能描述 : 判断黑名单成员是否已经存在
650 *****************************************************************************/
ipv4_deny_exist(const hmac_m2u_snoop_list_stru * snp_list,const osal_u32 * pul_grpaddr)651 OAL_STATIC osal_u8 ipv4_deny_exist(const hmac_m2u_snoop_list_stru *snp_list, const osal_u32 *pul_grpaddr)
652 {
653 osal_u8 ret = OSAL_FALSE;
654 osal_u8 idx;
655
656 for (idx = 0; idx < snp_list->deny_count_ipv4; idx++) {
657 if (*pul_grpaddr == snp_list->deny_group[idx]) { // 判断黑名单与列表是否相同
658 ret = OSAL_TRUE;
659 break;
660 }
661 }
662 return ret;
663 }
664
ipv6_deny_exist(hmac_m2u_snoop_list_stru * snp_list,const osal_u8 * grpaddr)665 OAL_STATIC osal_u8 ipv6_deny_exist(hmac_m2u_snoop_list_stru *snp_list, const osal_u8 *grpaddr)
666 {
667 osal_u8 ret = OSAL_FALSE;
668 osal_u8 idx;
669
670 for (idx = 0; idx < snp_list->deny_count_ipv6; idx++) {
671 if (osal_memcmp(grpaddr, snp_list->deny_group_ipv6[idx], OAL_IPV6_ADDR_SIZE) == 0) { // 判断黑名单与列表是否相同
672 ret = OSAL_TRUE;
673 break;
674 }
675 }
676 return ret;
677 }
678
679 /*****************************************************************************
680 函 数 名 : hmac_m2u_add__snoop_deny_entry
681 功能描述 : 增加黑名单成员
682 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IP地址
683 *****************************************************************************/
hmac_m2u_add_snoop_ipv4_deny_entry(hmac_vap_stru * hmac_vap,osal_u32 * pul_grpaddr)684 osal_void hmac_m2u_add_snoop_ipv4_deny_entry(hmac_vap_stru *hmac_vap, osal_u32 *pul_grpaddr)
685 {
686 osal_u8 idx;
687 hmac_m2u_snoop_list_stru *snp_list;
688 hmac_m2u_stru *m2u;
689
690 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
691 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_add_snoop_ipv4_deny_entry::hmac_vap is null}");
692 return;
693 }
694
695 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
696
697 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
698 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_add_snoop_ipv4_deny_entry::m2u is null}",
699 hmac_vap->vap_id);
700 return;
701 }
702
703 snp_list = &(m2u->m2u_snooplist);
704 idx = snp_list->deny_count_ipv4;
705 if (ipv4_deny_exist(snp_list, pul_grpaddr) != 0) { // 列表中已有
706 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:ADD ERROR, ALREADY EXISTS");
707 return;
708 }
709 /* ipv4和ipv6目前的黑名单个数相加超过最大黑名单个数 */
710 if (idx + snp_list->deny_count_ipv6 >= HMAC_M2U_GRPADDR_FILTEROUT_NUM) {
711 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:ADD ERROR, EXCEEDED LIMIT");
712 return;
713 }
714 snp_list->deny_count_ipv4++;
715 snp_list->deny_group[idx] = *pul_grpaddr;
716 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
717 return;
718 }
719
720 /*****************************************************************************
721 函 数 名 : hmac_m2u_add_snoop_ipv6_deny_entry
722 功能描述 : 增加IPV6黑名单成员
723 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IP地址
724 *****************************************************************************/
hmac_m2u_add_snoop_ipv6_deny_entry(hmac_vap_stru * hmac_vap,osal_u8 * grpaddr)725 osal_void hmac_m2u_add_snoop_ipv6_deny_entry(hmac_vap_stru *hmac_vap, osal_u8 *grpaddr)
726 {
727 osal_u8 idx;
728 hmac_m2u_snoop_list_stru *snp_list;
729 hmac_m2u_stru *m2u;
730
731 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
732 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_add_snoop_ipv6_deny_entry::hmac_vap is null}");
733 return;
734 }
735
736 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
737
738 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
739 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_add_snoop_ipv6_deny_entry::m2u is null}",
740 hmac_vap->vap_id);
741 return;
742 }
743 snp_list = &(m2u->m2u_snooplist);
744 idx = snp_list->deny_count_ipv6;
745 if (ipv6_deny_exist(snp_list, grpaddr) != 0) { // 列表中已有
746 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:ADD ERROR, ALREADY EXISTS");
747 return;
748 }
749 /* ipv4和ipv6目前的黑名单个数相加超过最大黑名单个数 */
750 if (idx + snp_list->deny_count_ipv4 >= HMAC_M2U_GRPADDR_FILTEROUT_NUM) {
751 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:ADD ERROR, EXCEEDED LIMIT");
752 return;
753 }
754 snp_list->deny_count_ipv6++;
755 if (memcpy_s(&snp_list->deny_group_ipv6[idx], OAL_SIZEOF(snp_list->deny_group_ipv6[idx]),
756 grpaddr, OAL_IPV6_ADDR_SIZE) != EOK) {
757 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_add_snoop_ipv6_deny_entry:memcpy addr fail", hmac_vap->vap_id);
758 }
759 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
760 return;
761 }
762
763 /*****************************************************************************
764 函 数 名 : hmac_m2u_del_ipv4_deny_entry
765 功能描述 : 删除黑名单成员
766 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IP地址
767 *****************************************************************************/
hmac_m2u_del_ipv4_deny_entry(hmac_vap_stru * hmac_vap,const osal_u32 * pul_grpaddr)768 osal_void hmac_m2u_del_ipv4_deny_entry(hmac_vap_stru *hmac_vap, const osal_u32 *pul_grpaddr)
769 {
770 osal_u8 idx;
771 osal_u8 num;
772 hmac_m2u_snoop_list_stru *snp_list;
773 hmac_m2u_stru *m2u;
774
775 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
776 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_del_ipv4_deny_entry::hmac_vap is null}");
777 return;
778 }
779
780 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
781
782 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
783 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_del_ipv4_deny_entry::m2u is null}",
784 hmac_vap->vap_id);
785 return;
786 }
787
788 snp_list = &(m2u->m2u_snooplist);
789 num = snp_list->deny_count_ipv4;
790
791 if (num <= DEFAULT_IPV4_DENY_GROUP_COUNT) {
792 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:DEL ERROR");
793 return;
794 }
795 if (*pul_grpaddr == snp_list->deny_group[0]) { // 删除默认地址
796 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:DEL ERROR, DEFAULE ADD");
797 return;
798 }
799 for (idx = DEFAULT_IPV4_DENY_GROUP_COUNT; idx < num; idx++) {
800 if (*pul_grpaddr == snp_list->deny_group[idx]) { // 4字节,共32位
801 break;
802 }
803 }
804
805 if (idx < num) {
806 snp_list->deny_group[idx] = snp_list->deny_group[num - 1];
807 snp_list->deny_count_ipv4--;
808 }
809 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
810 return;
811 }
812
813 /*****************************************************************************
814 函 数 名 : hmac_m2u_del_ipv6_deny_entry
815 功能描述 : 删除IPV6黑名单成员
816 输入参数 : hmac_vap vap结构体; grpaddr 组播组的IP地址
817 *****************************************************************************/
hmac_m2u_del_ipv6_deny_entry(hmac_vap_stru * hmac_vap,osal_u8 * grpaddr)818 osal_void hmac_m2u_del_ipv6_deny_entry(hmac_vap_stru *hmac_vap, osal_u8 *grpaddr)
819 {
820 osal_u8 idx;
821 osal_u8 num;
822 hmac_m2u_snoop_list_stru *snp_list;
823 hmac_m2u_stru *m2u;
824
825 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
826 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_del_ipv6_deny_entry::hmac_vap is null}");
827 return;
828 }
829
830 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
831
832 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
833 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_del_ipv6_deny_entry::m2u is null}",
834 hmac_vap->vap_id);
835 return;
836 }
837
838 snp_list = &(m2u->m2u_snooplist);
839 num = snp_list->deny_count_ipv6;
840
841 if (num <= DEFAULT_IPV6_DENY_GROUP_COUNT) {
842 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:DEL ERROR");
843 return;
844 }
845 if (osal_memcmp(grpaddr, snp_list->deny_group_ipv6[0], OAL_IPV6_ADDR_SIZE) == 0) {
846 oam_warning_log0(0, OAM_SF_M2U, "+NOTICE:DEL ERROR, DEFAULE ADD");
847 return;
848 }
849 for (idx = DEFAULT_IPV6_DENY_GROUP_COUNT; idx < num; idx++) {
850 if (osal_memcmp(grpaddr, snp_list->deny_group_ipv6[idx], OAL_IPV6_ADDR_SIZE) == 0) { // 16字节
851 break;
852 }
853 }
854
855 if (idx < num) {
856 if (memcpy_s(&snp_list->deny_group_ipv6[idx], OAL_SIZEOF(snp_list->deny_group_ipv6[idx]),
857 &snp_list->deny_group_ipv6[num - 1], OAL_IPV6_ADDR_SIZE) != EOK) {
858 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_del_ipv6_deny_entry:memcpy addr fail", hmac_vap->vap_id);
859 }
860 snp_list->deny_count_ipv6--;
861 }
862 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_deny_table OK}");
863 return;
864 }
865
hmac_m2u_print_grp_member_ip(const hmac_m2u_grp_member_stru * grp_member)866 OAL_STATIC osal_void hmac_m2u_print_grp_member_ip(const hmac_m2u_grp_member_stru *grp_member)
867 {
868 if (grp_member->src_ip_addr_len == OAL_IPV6_ADDR_SIZE) {
869 oam_info_log3(0, OAM_SF_M2U,
870 "group_src_ip_addr = [%02x]:[%02x]:[%02x]:[xx]:[xx]:[xx]:[xx]:[xx]",
871 oal_net2host_short(*(osal_u16 *)(&grp_member->src_ip_addr[0])),
872 oal_net2host_short(*(osal_u16 *)(&grp_member->src_ip_addr[2])), /* 2:组播组成员ip地址位 */
873 oal_net2host_short(*(osal_u16 *)(&grp_member->src_ip_addr[4]))); /* 4:组播组成员ip地址位 */
874 } else {
875 oam_info_log3(0, OAM_SF_M2U,
876 "group_src_ip_addr = [%d].[%d].[%d].[xxx]",
877 grp_member->src_ip_addr[0], grp_member->src_ip_addr[1],
878 grp_member->src_ip_addr[2]); /* 2:组播组成员ip地址位 */
879 }
880 }
881
hmac_m2u_print_grp_member_list(const hmac_m2u_grp_list_entry_stru * grp_list_member)882 OAL_STATIC osal_void hmac_m2u_print_grp_member_list(const hmac_m2u_grp_list_entry_stru *grp_list_member)
883 {
884 hmac_m2u_grp_member_stru *grp_member = OAL_PTR_NULL;
885 struct osal_list_head *member_entry_temp = OAL_PTR_NULL;
886 oal_snoop_group_stru snoop_group;
887 struct osal_list_head *grp_member_entry = OAL_PTR_NULL;
888
889 (osal_void)memset_s(&snoop_group, OAL_SIZEOF(oal_snoop_group_stru), 0, OAL_SIZEOF(oal_snoop_group_stru));
890
891 osal_list_for_each_safe(grp_member_entry, member_entry_temp, &(grp_list_member->src_list)) {
892 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry, hmac_m2u_grp_member_stru,
893 member_entry);
894 /* 打印组播组内成员的src ip地址和 mac地址 */
895 hmac_m2u_print_grp_member_ip(grp_member);
896
897 /* 打印 0 1 2 3 位mac */
898 oam_warning_log4(0, OAM_SF_M2U,
899 "sta_mac and mode = [%02x]:[%02x]:[%02x]:[%02x]:[xx]:[xx]",
900 grp_member->grp_member_mac[0], grp_member->grp_member_mac[1],
901 grp_member->grp_member_mac[2], /* 打印 0 1 2 3 位mac */
902 grp_member->grp_member_mac[3]); /* 打印 0 1 2 3 位mac */
903 oam_warning_log1(0, OAM_SF_M2U, "mode %d", grp_member->mode);
904 }
905 }
906
907 /* 输出snoop表所有成员 */
hmac_m2u_print_all_snoop_list(hmac_vap_stru * hmac_vap,oal_snoop_all_group_stru * snoop_all_grp)908 osal_u32 hmac_m2u_print_all_snoop_list(hmac_vap_stru *hmac_vap, oal_snoop_all_group_stru *snoop_all_grp)
909 {
910 hmac_m2u_snoop_list_stru *snp_list = OAL_PTR_NULL;
911 hmac_m2u_grp_list_entry_stru *grp_list_member = OAL_PTR_NULL;
912 struct osal_list_head *grp_list_entry = OAL_PTR_NULL;
913 hmac_m2u_stru *m2u = OAL_PTR_NULL;
914 osal_u16 group_cnt = 0;
915
916 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
917 oam_warning_log0(0, OAM_SF_M2U, "hmac_m2u_print_all_snoop_list::hmac_vap is null}");
918 return OAL_ERR_CODE_PTR_NULL;
919 }
920
921 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
922 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
923 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_print_all_snoop_list::m2u is null}",
924 hmac_vap->vap_id);
925 return OAL_ERR_CODE_PTR_NULL;
926 }
927
928 snp_list = &(m2u->m2u_snooplist);
929 if (snp_list == OAL_PTR_NULL) {
930 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] hmac_m2u_print_all_snoop_list::snp_list is null}",
931 hmac_vap->vap_id);
932 return OAL_ERR_CODE_PTR_NULL;
933 }
934
935 oam_warning_log4(0, OAM_SF_M2U, "sta_num: [%d] group_num:[%d] snoop_enable:[%d] vap_mode:[%d]",
936 snp_list->total_sta_num, snp_list->group_list_count, m2u->snoop_enable, hmac_vap->vap_mode);
937
938 if ((hmac_vap->vap_mode == WLAN_VAP_MODE_BSS_AP) && (m2u->snoop_enable == OAL_TRUE)) {
939 if (snoop_all_grp != OAL_PTR_NULL) {
940 snoop_all_grp->group_cnt = snp_list->group_list_count;
941 group_cnt = 0;
942 }
943 osal_list_for_each(grp_list_entry, &(snp_list->grp_list)) {
944 grp_list_member = (hmac_m2u_grp_list_entry_stru *)osal_list_entry(grp_list_entry,
945 hmac_m2u_grp_list_entry_stru, grp_entry);
946 /* 打印组播组的mac地址 */
947 oam_warning_log4(0, OAM_SF_M2U,
948 "group addr = [%02x]:[%02x]:[%02x]:[%02x]:[xx]:[xx]",
949 grp_list_member->group_mac[0], grp_list_member->group_mac[1],
950 grp_list_member->group_mac[2], grp_list_member->group_mac[3]); /* 打印 0 1 2 3 位mac */
951 oam_warning_log1(0, OAM_SF_M2U, "vlan tag = 0x%x", *(osal_u32 *)(&(grp_list_member->outer_vlan_tag)));
952 hmac_m2u_print_grp_member_list(grp_list_member);
953 if (snoop_all_grp != OAL_PTR_NULL) {
954 group_cnt++;
955 }
956 }
957 } else {
958 oam_warning_log2(0, OAM_SF_M2U, "{hmac_m2u_print_all_snoop_list::snoop_enable vap_mode = [%d].[%d]}",
959 m2u->snoop_enable, hmac_vap->vap_mode);
960 }
961 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_list OK}");
962 return OAL_SUCC;
963 }
964
965 /*****************************************************************************
966 函 数 名 : hmac_m2u_get_group_mac
967 功能描述 : 根据组播组ip地址获取组播组mac地址
968 输入参数 : group_ip指向ip地址的指针; ip_len ip地址长度
969 输出参数 : group_mac 存储组播组mac地址的指针
970 *****************************************************************************/
hmac_m2u_get_group_mac(osal_u8 * group_mac,osal_u8 * group_ip,osal_u8 ip_len)971 OAL_STATIC osal_void hmac_m2u_get_group_mac(osal_u8 *group_mac, osal_u8 *group_ip, osal_u8 ip_len)
972 {
973 osal_u8 *group_ip_tmp = group_ip;
974 const osal_u8 group_mac_len_ipv6 = 4; /* 取最后4个字节 */
975 const osal_u8 group_mac_len_ipv4 = 3; /* 3:组播组成员mac地址位 */
976
977 if (ip_len == OAL_IPV6_ADDR_SIZE) {
978 // ipv6下,组播mac最后4字节由IP地址映射而来
979 group_mac[0] = 0x33;
980 group_mac[1] = 0x33;
981 group_mac += 2; /* 2:跳过前面已赋值字节 */
982 group_ip_tmp += 12; // 12取最后4个字节
983 if (memcpy_s(group_mac, group_mac_len_ipv6, group_ip_tmp, 4) != EOK) { /* 取最后4个字节 */
984 oam_warning_log0(0, OAM_SF_M2U, "hmac_m2u_get_group_mac:memcpy addr fail");
985 }
986 oam_info_log4(0, OAM_SF_M2U,
987 "{hmac_m2u_get_group_mac::ipv6 multicast packets are restored to unicast , \
988 the group mac [%02x][%02x][%02x][%02x][xx][xx]}", \
989 group_mac[0], group_mac[1], group_mac[2], group_mac[3]); /* 打印第0、1、2、3位mac */
990 } else {
991 // ipv4下,组播mac最后23bit由IP地址映射而来
992 group_mac[0] = 0x01;
993 group_mac[1] = 0x0;
994 group_mac[2] = 0x5e; /* 2:组播组成员mac地址位 */
995 group_ip_tmp += 1;
996 if (memcpy_s(group_mac + 3, group_mac_len_ipv4, group_ip_tmp, 3) != EOK) { /* 3:组播组成员mac地址位 */
997 oam_warning_log0(0, OAM_SF_M2U, "hmac_m2u_get_group_mac:memcpy addr fail");
998 }
999 group_mac[3] &= 0x7f; /* 3:组播组成员mac地址位 */
1000 oam_info_log4(0, OAM_SF_M2U,
1001 "{hmac_m2u_get_group_mac::ipv4 multicast packets are restored to unicast , \
1002 the group mac [%02x][%02x][%02x][%02x][xx][xx]}", \
1003 group_mac[0], group_mac[1], group_mac[2], group_mac[3]); /* 打印第0、1、2、3位mac */
1004 }
1005 }
1006
1007 /*****************************************************************************
1008 函 数 名 : hmac_m2u_igmp_v1v2_update
1009 功能描述 : IGMP V1 V2 报文更新snoop链表
1010 输入参数 : hmac_vap vap结构体; list_entry 待更新的节点结构体; igmp IGMP报文结构体
1011 *****************************************************************************/
hmac_m2u_igmp_v1v2_update(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,mac_igmp_header_stru * igmp)1012 osal_u32 hmac_m2u_igmp_v1v2_update(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1013 mac_igmp_header_stru *igmp)
1014 {
1015 osal_u32 group_addr; /* to hold group address from group record */
1016 osal_u32 ul_ret = OAL_SUCC;
1017
1018 group_addr = igmp->group;
1019 if (hmac_m2u_snoop_is_denied_ipv4(hmac_vap, oal_net2host_long(group_addr)) != 0) {
1020 oam_warning_log3(0, OAM_SF_M2U, "{hmac_m2u_igmp_v1v2_update::group_addr[%02x].[%02x].[%02x].[xx] is denied}}",
1021 (osal_u32)((group_addr) & 0xff), (osal_u32)((group_addr>> 8) & 0xff), /* 8:偏移取值 */
1022 (osal_u32)((group_addr>> 16) & 0xff)); /* 16,24:偏移取值 */
1023 return ul_ret;
1024 }
1025
1026 if (igmp->type != MAC_IGMPV2_LEAVE_TYPE) {
1027 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1028 } else {
1029 list_entry->cmd = HMAC_M2U_CMD_EXCLUDE_LIST;
1030 }
1031
1032 list_entry->src_ip_addr_len = OAL_IPV4_ADDR_SIZE;
1033 hmac_m2u_get_group_mac(list_entry->grp_mac, (osal_u8 *)(&group_addr), OAL_IPV4_ADDR_SIZE);
1034 memset_s(list_entry->src_ip_addr, OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
1035 ul_ret = hmac_m2u_update_snoop_list(list_entry);
1036 return ul_ret;
1037 }
1038
hmac_m2u_exc_update(hmac_vap_stru * hmac_vap,osal_u16 no_srec,hmac_m2u_list_update_stru * list_entry,osal_u32 * ret)1039 OAL_STATIC osal_void hmac_m2u_exc_update(hmac_vap_stru *hmac_vap, osal_u16 no_srec,
1040 hmac_m2u_list_update_stru *list_entry, osal_u32 *ret)
1041 {
1042 hmac_m2u_grp_list_entry_stru *grp_list = OAL_PTR_NULL;
1043
1044 list_entry->cmd = HMAC_M2U_CMD_EXCLUDE_LIST;
1045 grp_list = hmac_m2u_find_group_list(hmac_vap, list_entry);
1046 /* 更新组播组内成员的状态,如果组播组内存在该目标成员,则清空目标成员 */
1047 if (grp_list == OAL_PTR_NULL) {
1048 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_exc_update::grp_list is null.}",
1049 hmac_vap->vap_id);
1050 } else {
1051 hmac_m2u_remove_one_member(grp_list, hmac_vap, list_entry->new_member_mac);
1052 }
1053
1054 /* 更新组播组内成员的状态,如果组播组内不存在该目标成员,该成员inc所有src ip */
1055 if (no_srec == 0) {
1056 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_exc_update::not exist the user no_srec is %d}",
1057 hmac_vap->vap_id, no_srec);
1058 (osal_void)memset_s(list_entry->src_ip_addr, OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
1059 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1060 *ret = hmac_m2u_update_snoop_list(list_entry);
1061 }
1062 }
1063
hmac_m2u_inc_update(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry)1064 OAL_STATIC osal_void hmac_m2u_inc_update(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry)
1065 {
1066 hmac_m2u_grp_list_entry_stru *grp_list = OAL_PTR_NULL;
1067
1068 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1069 grp_list = hmac_m2u_find_group_list(hmac_vap, list_entry);
1070 if (grp_list == OAL_PTR_NULL) {
1071 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_inc_update::grp_list is null.}",
1072 hmac_vap->vap_id);
1073 } else {
1074 hmac_m2u_remove_one_member(grp_list, hmac_vap, list_entry->new_member_mac);
1075 }
1076 }
1077
hmac_m2u_delete_old_source_records(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,hmac_m2u_stru * m2u)1078 OAL_STATIC osal_void hmac_m2u_delete_old_source_records(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1079 hmac_m2u_stru *m2u)
1080 {
1081 hmac_m2u_grp_list_entry_stru *grp_list = OAL_PTR_NULL;
1082 hmac_m2u_grp_member_stru *grp_member_list = OAL_PTR_NULL;
1083
1084 grp_list = hmac_m2u_find_group_list(hmac_vap, list_entry);
1085 if (grp_list == OAL_PTR_NULL) {
1086 return;
1087 }
1088 grp_member_list = hmac_m2u_find_member_src(grp_list, list_entry->new_member_mac, list_entry->src_ip_addr);
1089 if (grp_member_list == OAL_PTR_NULL) {
1090 return;
1091 }
1092 osal_list_del(&grp_member_list->member_entry);
1093 oal_mem_free(grp_member_list, OAL_TRUE);
1094
1095 oam_warning_log3(0, OAM_SF_M2U,
1096 "vap_id[%d] {hmac_m2u_delete_old_source_records:: current total_sta_num:[%d] ,sta_num:[%d]}",
1097 hmac_vap->vap_id, m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
1098
1099 grp_list->sta_num--;
1100 m2u->m2u_snooplist.total_sta_num--;
1101
1102 oam_warning_log3(0, OAM_SF_M2U,
1103 "vap_id[%d]{hmac_m2u_delete_old_source_records::remove one sta current total_sta_num[%d]sta_num[%d]}",
1104 hmac_vap->vap_id, m2u->m2u_snooplist.total_sta_num, grp_list->sta_num);
1105 }
1106
hmac_m2u_igmp_v3_update_list(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,hmac_m2u_stru * m2u,mac_igmp_v3_grec_stru * grec,osal_u32 * ret)1107 OAL_STATIC osal_void hmac_m2u_igmp_v3_update_list(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1108 hmac_m2u_stru *m2u, mac_igmp_v3_grec_stru *grec, osal_u32 *ret)
1109 {
1110 osal_u32 *src_addr = OAL_PTR_NULL; /* 组播源的IP地址 */
1111 osal_u16 no_srec; /* no of source records */
1112
1113 no_srec = oal_host2net_short(grec->grec_nsrcs);
1114
1115 /* IGMP V3 exc的处理 */
1116 if ((grec->grec_type == IGMPV3_CHANGE_TO_EXCLUDE) || (grec->grec_type == IGMPV3_MODE_IS_EXCLUDE)) {
1117 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_igmp_v3_update::grec->grec_type is %d.}",
1118 hmac_vap->vap_id, grec->grec_type);
1119 hmac_m2u_exc_update(hmac_vap, no_srec, list_entry, ret);
1120 } else if ((grec->grec_type == IGMPV3_CHANGE_TO_INCLUDE) || (grec->grec_type == IGMPV3_MODE_IS_INCLUDE)) {
1121 /* IGMP V3 INC的处理 */
1122 hmac_m2u_inc_update(hmac_vap, list_entry);
1123 } else if (grec->grec_type == IGMPV3_ALLOW_NEW_SOURCES) {
1124 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1125 }
1126
1127 src_addr = (osal_u32 *)((osal_u8 *)grec + OAL_SIZEOF(mac_igmp_v3_grec_stru));
1128
1129 /* 同一组播组内不同src ip的链表更新 */
1130 while (no_srec != 0) {
1131 *(osal_u32 *)(list_entry->src_ip_addr) = *src_addr;
1132 if (grec->grec_type != IGMPV3_BLOCK_OLD_SOURCES) {
1133 *ret = hmac_m2u_update_snoop_list(list_entry);
1134 } else { /* block old source时清空该成员 */
1135 hmac_m2u_delete_old_source_records(hmac_vap, list_entry, m2u);
1136 }
1137 src_addr++;
1138 no_srec--;
1139 }
1140 }
1141
1142 /* IGMP V3报文更新snoop链表 */
hmac_m2u_igmp_v3_update(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,mac_igmp_v3_report_stru * igmpr3)1143 OAL_STATIC osal_u32 hmac_m2u_igmp_v3_update(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1144 mac_igmp_v3_report_stru *igmpr3)
1145 {
1146 osal_u32 group_ip; /* to hold group ip address from group record */
1147 osal_u16 no_grec; /* no of group records */
1148 mac_igmp_v3_grec_stru *grec = OAL_PTR_NULL; /* igmp group record */
1149 hmac_m2u_stru *m2u = OAL_PTR_NULL;
1150 osal_u32 ret = OAL_SUCC;
1151
1152 no_grec = oal_host2net_short(igmpr3->ngrec);
1153 grec = (mac_igmp_v3_grec_stru *)(igmpr3 + 1);
1154 m2u = (hmac_m2u_stru *)(list_entry->hmac_vap->m2u);
1155
1156 if (no_grec == 0) {
1157 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_igmp_v3_update::no_grec is 0.}",
1158 hmac_vap->vap_id);
1159 return OAL_FAIL;
1160 }
1161
1162 while (no_grec != 0) {
1163 list_entry->cmd = grec->grec_type;
1164 group_ip = grec->grec_group_ip; // 获取组播组ip地址
1165
1166 if (hmac_m2u_snoop_is_denied_ipv4(hmac_vap, oal_net2host_long(group_ip)) != 0) {
1167 oam_warning_log3(0, OAM_SF_M2U,
1168 "{hmac_m2u_igmp_v3_update::group_addr [%02x].[%02x].[%02x].[xx] is denied}}",
1169 (osal_u32)((group_ip >> 24) & 0xff), (osal_u32)((group_ip >> 16) & 0xff), /* 24,16:偏移取值 */
1170 (osal_u32)((group_ip >> 8) & 0xff)); /* 8:偏移取值 */
1171 /* move the grec to next group record */
1172 grec = (mac_igmp_v3_grec_stru *)((osal_u8 *)grec + igmpv3_grp_rec_len(grec));
1173 no_grec--;
1174 continue;
1175 }
1176 /* 非IGMPV3六种cmd的异常处理 */
1177 if (!is_igmpv3_mode(grec->grec_type)) {
1178 oam_info_log2(0, OAM_SF_M2U,
1179 "vap_id[%d] {hmac_m2u_igmp_v3_update::grec_type is [%x] not inside the six cmd.}",
1180 hmac_vap->vap_id, grec->grec_type);
1181 /* move the grec to next group record */
1182 grec = (mac_igmp_v3_grec_stru *)((osal_u8 *)grec + igmpv3_grp_rec_len(grec));
1183 no_grec--;
1184 continue;
1185 }
1186
1187 hmac_m2u_get_group_mac(list_entry->grp_mac, (osal_u8 *)(&group_ip), OAL_IPV4_ADDR_SIZE);
1188 list_entry->src_ip_addr_len = OAL_IPV4_ADDR_SIZE;
1189
1190 hmac_m2u_igmp_v3_update_list(hmac_vap, list_entry, m2u, grec, &ret);
1191
1192 /* 取下一个组播组 */
1193 grec = (mac_igmp_v3_grec_stru *)((osal_u8 *)grec + igmpv3_grp_rec_len(grec));
1194 no_grec--;
1195 }
1196 return ret;
1197 }
1198
1199 /*****************************************************************************
1200 函 数 名 : hmac_m2u_mld_v1_update
1201 功能描述 : MLDV1 报文更新snoop链表
1202 输入参数 : hmac_vap vap结构体; list_entry 待更新的节点结构体; mld_head MLD报文结构体
1203 *****************************************************************************/
hmac_m2u_mld_v1_update(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,mac_mld_v1_head_stru * mld_head)1204 OAL_STATIC osal_u32 hmac_m2u_mld_v1_update(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1205 mac_mld_v1_head_stru *mld_head)
1206 {
1207 osal_u32 ul_ret = OAL_SUCC;
1208 if (hmac_m2u_snoop_is_denied_ipv6(hmac_vap, mld_head->group_ip) != 0) {
1209 oam_warning_log1(0, OAM_SF_M2U, "{hmac_m2u_mld_v1_update::group_ip \
1210 [%08x]:[xxxxxxxx]:[xxxxxxxx]:[xxxxxxxx] is denied}}",\
1211 oal_host2net_long(*(osal_u32 *)(&mld_head->group_ip[0])));
1212
1213 return ul_ret;
1214 }
1215
1216 /* 初始化组播组地址 */
1217 hmac_m2u_get_group_mac(list_entry->grp_mac, mld_head->group_ip, OAL_IPV6_ADDR_SIZE);
1218
1219 if (mld_head->type != MLDV1_DONE_TYPE) {
1220 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1221 } else {
1222 list_entry->cmd = HMAC_M2U_CMD_EXCLUDE_LIST;
1223 }
1224 list_entry->src_ip_addr_len = OAL_IPV6_ADDR_SIZE;
1225 memset_s(list_entry->src_ip_addr, OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
1226 ul_ret = hmac_m2u_update_snoop_list(list_entry);
1227 return ul_ret;
1228 }
1229
hmac_m2u_mld_v2_update_list(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,hmac_m2u_stru * m2u,mac_mld_v2_group_record_stru * grec,osal_u32 * ret)1230 OAL_STATIC osal_void hmac_m2u_mld_v2_update_list(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1231 hmac_m2u_stru *m2u, mac_mld_v2_group_record_stru *grec, osal_u32 *ret)
1232 {
1233 osal_u16 no_srec; /* no of source records */
1234 osal_u8 *src_addr = OAL_PTR_NULL; /* 组播源的IP地址 */
1235
1236 no_srec = oal_host2net_short(grec->grec_srcaddr_num);
1237
1238 /* MLD V2 exc的处理 */
1239 if ((grec->grec_type == MLDV2_CHANGE_TO_EXCLUDE) || (grec->grec_type == MLDV2_MODE_IS_EXCLUDE)) {
1240 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_mld_v2_update_list::grec->grec_type is %d.}",
1241 hmac_vap->vap_id, grec->grec_type);
1242 hmac_m2u_exc_update(hmac_vap, no_srec, list_entry, ret);
1243 } else if ((grec->grec_type == MLDV2_CHANGE_TO_INCLUDE) || (grec->grec_type == MLDV2_MODE_IS_INCLUDE)) {
1244 /* MLD V2 INC的处理 */
1245 hmac_m2u_inc_update(hmac_vap, list_entry);
1246 } else if (grec->grec_type == MLDV2_ALLOW_NEW_SOURCES) {
1247 list_entry->cmd = HMAC_M2U_CMD_INCLUDE_LIST;
1248 }
1249
1250 src_addr = (osal_u8 *)grec + OAL_SIZEOF(mac_mld_v2_group_record_stru);
1251
1252 /* 同一组播组内不同src ip的链表更新 */
1253 while (no_srec != 0) {
1254 if (memcpy_s(list_entry->src_ip_addr, sizeof(list_entry->src_ip_addr), src_addr,
1255 OAL_IPV6_ADDR_SIZE) != EOK) {
1256 oam_warning_log0(0, OAM_SF_M2U, "{hmac_m2u_mld_v2_update_list::memcpy src_addr fail.}");
1257 }
1258 if (grec->grec_type != MLDV2_BLOCK_OLD_SOURCES) {
1259 *ret = hmac_m2u_update_snoop_list(list_entry);
1260 } else { /* block old source时清空该成员 */
1261 hmac_m2u_delete_old_source_records(hmac_vap, list_entry, m2u);
1262 }
1263 src_addr += OAL_IPV6_ADDR_SIZE;
1264 no_srec--;
1265 }
1266 }
1267
hmac_m2u_mldv2_grp_rec_len(mac_mld_v2_group_record_stru * grec)1268 OAL_STATIC osal_u32 hmac_m2u_mldv2_grp_rec_len(mac_mld_v2_group_record_stru *grec)
1269 {
1270 return OAL_SIZEOF(mac_mld_v2_group_record_stru) + (grec->grec_srcaddr_num << 4) + grec->grec_auxwords; /* 4 */
1271 }
1272
1273 /* MLDV1 报文更新snoop链表 */
hmac_m2u_mld_v2_update(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,mac_mld_v2_report_stru * mldv2)1274 OAL_STATIC osal_u32 hmac_m2u_mld_v2_update(hmac_vap_stru *hmac_vap, hmac_m2u_list_update_stru *list_entry,
1275 mac_mld_v2_report_stru *mldv2)
1276 {
1277 osal_u16 no_grec; /* no of group records */
1278 mac_mld_v2_group_record_stru *grec = OAL_PTR_NULL; /* igmp group record */
1279 hmac_m2u_stru *m2u = OAL_PTR_NULL;
1280 osal_u32 ret = OAL_SUCC;
1281
1282 no_grec = oal_host2net_short(mldv2->group_address_num);
1283 grec = (mac_mld_v2_group_record_stru *)(mldv2 + 1);
1284 m2u = (hmac_m2u_stru *)(list_entry->hmac_vap->m2u);
1285
1286 if (no_grec == 0) {
1287 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_mld_v2_update::no_grec is 0.}",
1288 hmac_vap->vap_id);
1289 return OAL_FAIL;
1290 }
1291
1292 while (no_grec != 0) {
1293 list_entry->cmd = grec->grec_type;
1294 if (hmac_m2u_snoop_is_denied_ipv6(hmac_vap, grec->group_ip) != 0) {
1295 oam_warning_log1(0, OAM_SF_M2U,
1296 "{hmac_m2u_mld_v2_update::group_ip [%08x]:[xxxxxxxx]:[xxxxxxxx]:[xxxxxxxx] is denied}}",
1297 oal_host2net_long(*(osal_u32 *)(&grec->group_ip[0]))); /* 只打印32bit */
1298 grec = (mac_mld_v2_group_record_stru *)((osal_u8 *)grec + hmac_m2u_mldv2_grp_rec_len(grec));
1299 no_grec--;
1300 continue;
1301 }
1302
1303 /* 非MLDV2六种cmd的异常处理 */
1304 if (!is_mldv2_mode(grec->grec_type)) {
1305 oam_warning_log2(0, OAM_SF_M2U,
1306 "vap_id[%d] {hmac_m2u_mld_v2_update::grec_type is [%x] not inside the six cmd.}",
1307 hmac_vap->vap_id, grec->grec_type);
1308 /* move the grec to next group record */
1309 grec = (mac_mld_v2_group_record_stru *)((osal_u8 *)grec + hmac_m2u_mldv2_grp_rec_len(grec));
1310 no_grec--;
1311 continue;
1312 }
1313
1314 hmac_m2u_get_group_mac(list_entry->grp_mac, grec->group_ip, OAL_IPV6_ADDR_SIZE);
1315 list_entry->src_ip_addr_len = OAL_IPV6_ADDR_SIZE;
1316 hmac_m2u_mld_v2_update_list(hmac_vap, list_entry, m2u, grec, &ret);
1317
1318 /* 取下一个组播组 */
1319 grec = (mac_mld_v2_group_record_stru *)((osal_u8 *)grec + hmac_m2u_mldv2_grp_rec_len(grec));
1320 no_grec--;
1321 }
1322 return ret;
1323 }
1324
1325 /*****************************************************************************
1326 函 数 名 : hmac_m2u_snoop_inspecting_ipv4
1327 功能描述 :解析ipv4 下的IGMP报文
1328 输入参数 : hmac_vap vap结构体; hmac_user user结构体; buf netbuf结构体
1329 *****************************************************************************/
hmac_m2u_snoop_inspecting_ipv4(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hmac_m2u_list_update_stru * list_entry,osal_u8 * buf)1330 OAL_STATIC osal_void hmac_m2u_snoop_inspecting_ipv4(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
1331 hmac_m2u_list_update_stru *list_entry, osal_u8 *buf)
1332 {
1333 mac_ip_header_stru *ip_hdr;
1334 mac_igmp_header_stru *igmp; /* igmp header for v1 and v2 */
1335 mac_igmp_v3_report_stru *igmpr3; /* igmp header for v3 */
1336 osal_u8 ip_hdr_len;
1337
1338 /* 取ip头 */
1339 ip_hdr = (mac_ip_header_stru *)buf;
1340
1341 if (ip_hdr->protocol != IPPROTO_IGMP) {
1342 return;
1343 }
1344
1345 list_entry->hmac_vap = hmac_vap;
1346 list_entry->hmac_user = hmac_user;
1347
1348 /* bit序不同,取不同的ip头长度 */
1349 if (oal_netbuf_get_bitfield() == OAL_BITFIELD_BIG_ENDIAN) {
1350 ip_hdr_len = ip_hdr->version_ihl & 0x0F;
1351 } else {
1352 ip_hdr_len = (ip_hdr->version_ihl & 0xF0) >> 4; /* 4:偏移取值 */
1353 }
1354 if (ip_hdr_len < MIN_IP_HDR_LEN) {
1355 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv4::ip_hdr_len is [%x].}",
1356 hmac_vap->vap_id, ip_hdr_len);
1357 return;
1358 }
1359 /* v1 & v2 igmp */
1360 igmp = (mac_igmp_header_stru *)(buf + (ip_hdr_len << 2));
1361
1362 /* v3 igmp */
1363 igmpr3 = (mac_igmp_v3_report_stru *)igmp;
1364
1365 /* 如果报文不是IGMP report报文或leave报文,不进行链表更新 */
1366 if (is_igmp_report_leave_packet(igmp->type) == 0) {
1367 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv4::not igmp report[%x].}",
1368 hmac_vap->vap_id, igmp->type);
1369 return;
1370 }
1371
1372 /* IGMP v1 v2 报文的链表更新 */
1373 if (igmp->type != MAC_IGMPV3_REPORT_TYPE) {
1374 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv4::v1v2 update[%x].}",
1375 hmac_vap->vap_id, igmp->type);
1376 hmac_m2u_igmp_v1v2_update(hmac_vap, list_entry, igmp);
1377 } else { /* IGMP v3 report 报文的链表更新 */
1378 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv4::v3 update[%x].}",
1379 hmac_vap->vap_id, igmp->type);
1380 hmac_m2u_igmp_v3_update(hmac_vap, list_entry, igmpr3);
1381 }
1382 }
1383
1384 /*****************************************************************************
1385 函 数 名 : hmac_m2u_snoop_inspecting_ipv6
1386 功能描述 :解析ipv6 下的MLD报文
1387 输入参数 : hmac_vap vap结构体; hmac_user user结构体; buf netbuf结构体
1388 *****************************************************************************/
hmac_m2u_snoop_inspecting_ipv6(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hmac_m2u_list_update_stru * list_entry,osal_u8 * buf)1389 OAL_STATIC osal_void hmac_m2u_snoop_inspecting_ipv6(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
1390 hmac_m2u_list_update_stru *list_entry, osal_u8 *buf)
1391 {
1392 oal_ipv6hdr_stru *ip_hdr;
1393 mac_mld_v2_report_stru *mldv2; /* mld report header for v2 */
1394 mac_mld_v1_head_stru *mld_head;
1395 oal_icmp6hdr_stru *icmp_head;
1396
1397 /* 取ip头 */
1398 ip_hdr = (oal_ipv6hdr_stru *)(buf);
1399 icmp_head = (oal_icmp6hdr_stru *)(ip_hdr + 1); // 跳过IPV6 头获取ICMPV6头
1400
1401 if ((icmp_head->icmp6_type != OAL_IPPROTO_ICMPV6) || (ip_hdr->nexthdr != 0x0)) {
1402 return;
1403 }
1404
1405 mld_head = (mac_mld_v1_head_stru *)(icmp_head + 1); // 跳过IPV6 头获取ICMPV6头
1406 if (is_mld_report_leave_packet(mld_head->type) == 0) {
1407 return;
1408 }
1409
1410 list_entry->hmac_vap = hmac_vap;
1411 list_entry->hmac_user = hmac_user;
1412 mldv2 = (mac_mld_v2_report_stru *) mld_head;
1413
1414 /* MLD v1 报文的链表更新 */
1415 if (mld_head->type != MLDV2_REPORT_TYPE) {
1416 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv6::v1 update[%x].}",
1417 hmac_vap->vap_id, mld_head->type);
1418 hmac_m2u_mld_v1_update(hmac_vap, list_entry, mld_head);
1419 } else { /* MLD v2 report 报文的链表更新 */
1420 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting_ipv6::v2 update[%x].}",
1421 hmac_vap->vap_id, mld_head->type);
1422 hmac_m2u_mld_v2_update(hmac_vap, list_entry, mldv2);
1423 }
1424 }
1425
1426 /*****************************************************************************
1427 功能描述 : 获取外层vlan tag
1428 *****************************************************************************/
hmac_m2u_snoop_inspecting_get_vlan_tag(hmac_vap_stru * hmac_vap,hmac_m2u_list_update_stru * list_entry,const mac_vlan_tag_stru * vlan_tag)1429 OAL_STATIC osal_void hmac_m2u_snoop_inspecting_get_vlan_tag(hmac_vap_stru *hmac_vap,
1430 hmac_m2u_list_update_stru *list_entry, const mac_vlan_tag_stru *vlan_tag)
1431 {
1432 if (memcpy_s(&(list_entry->outer_vlan_tag), OAL_SIZEOF(list_entry->outer_vlan_tag),
1433 vlan_tag, OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) { // 存放vlan信息
1434 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_snoop_inspecting_get_vlan_tag:memcpy fail", hmac_vap->vap_id);
1435 }
1436 }
1437
1438 /*****************************************************************************
1439 函 数 名 : hmac_m2u_snoop_inspecting
1440 功能描述 : 监听IGMP报文来创建组播组链表
1441 输入参数 : hmac_vap vap结构体; hmac_user user结构体; buf netbuf结构体
1442 *****************************************************************************/
hmac_m2u_snoop_inspecting(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * buf)1443 osal_void hmac_m2u_snoop_inspecting(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, oal_netbuf_stru *buf)
1444 {
1445 mac_ether_header_stru *ether_header = (mac_ether_header_stru *)oal_netbuf_data(buf);
1446 /* source address which send the report and it is the member */
1447 /* list entry where all member details will be updated and passed on updating the snoop list */
1448 hmac_m2u_list_update_stru list_entry;
1449 mac_vlan_tag_stru *vlan_tag = OSAL_NULL;
1450 osal_u16 ether_data_type;
1451 osal_u8 *ip_head = OSAL_NULL;
1452
1453 if (((hmac_m2u_stru *)(hmac_vap->m2u))->snoop_enable == OAL_FALSE) {
1454 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting::snoop is not enable}", hmac_vap->vap_id);
1455 return;
1456 }
1457
1458 memset_s(&list_entry, OAL_SIZEOF(hmac_m2u_list_update_stru), 0, OAL_SIZEOF(hmac_m2u_list_update_stru));
1459
1460 /* 设置mac地址 */
1461 oal_set_mac_addr((osal_u8 *)list_entry.new_member_mac, (const osal_u8 *)ether_header->ether_shost);
1462
1463 /* 带vlan tag 的情况 */
1464 if (ether_is_with_vlan_tag(ether_header->ether_type)) {
1465 // 偏移2个mac地址的长度,获取外层vlan tag
1466 vlan_tag = (mac_vlan_tag_stru *)(oal_netbuf_data(buf) + (ETHER_ADDR_LEN << 1));
1467 hmac_m2u_snoop_inspecting_get_vlan_tag(hmac_vap, &list_entry, vlan_tag);
1468
1469 vlan_tag += 1; // 判断内层tag
1470 if (ether_is_with_vlan_tag(vlan_tag->tpid)) {
1471 vlan_tag += 1; // 不考虑内层tag,跳过
1472 }
1473
1474 ether_data_type = *((osal_u16 *)(vlan_tag)); // 跳过tag后获取eth type
1475 ip_head = (osal_u8 *)(vlan_tag) + 2; // 2:跳过 type 指向ip头起始地址
1476 } else { /* 非vlan 的情况 */
1477 ip_head = (osal_u8 *)(ether_header + 1);
1478 ether_data_type = ether_header->ether_type;
1479 }
1480
1481 /* ap模式的接收处理 */
1482 if ((hmac_vap->vap_mode == WLAN_VAP_MODE_BSS_AP) && (!ETHER_IS_BROADCAST(ether_header->ether_dhost))) {
1483 if ((ether_data_type == oal_host2net_short(ETHER_TYPE_IP)) &&
1484 (ether_is_ipv4_multicast(ether_header->ether_dhost) != 0)) {
1485 hmac_m2u_snoop_inspecting_ipv4(hmac_vap, hmac_user, &list_entry, ip_head);
1486 } else if ((ether_data_type == oal_host2net_short(ETHER_TYPE_IPV6)) &&
1487 ETHER_IS_IPV6_MULTICAST(ether_header->ether_dhost)) {
1488 hmac_m2u_snoop_inspecting_ipv6(hmac_vap, hmac_user, &list_entry, ip_head);
1489 } else {
1490 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_inspecting::ether type is not IP Protocol.[0x%x]}",
1491 hmac_vap->vap_id, oal_host2net_short(ether_header->ether_type));
1492 return;
1493 }
1494 }
1495 /* STA模式的接收处理 去掉自定义的tunnel协议头 */
1496 if ((ether_header->ether_type == oal_host2net_short(ETHER_TUNNEL_TYPE)) &&
1497 (hmac_vap->vap_mode == WLAN_VAP_MODE_BSS_STA)) {
1498 oam_info_log1(0, OAM_SF_M2U, "vap[%d]{hmac_m2u_snoop_inspecting:STA && ETHER_TUNNELTYPE}", hmac_vap->vap_id);
1499 oal_netbuf_pull(buf, OAL_SIZEOF(mac_ether_header_stru));
1500 oal_netbuf_pull(buf, OAL_SIZEOF(mcast_tunnel_hdr_stru));
1501 }
1502 return;
1503 }
1504
1505 /*****************************************************************************
1506 函 数 名 : hmac_m2u_count_member_anysrclist
1507 功能描述 : 找出一个组播组内,组播源为所有源的所有STA用户
1508 输入参数 : grp_list 组播组结构体; table 组播组成员所在指针数组; timestamp nowtime变量
1509 输出参数 : count
1510 *****************************************************************************/
hmac_m2u_count_member_anysrclist(hmac_m2u_grp_list_entry_stru * grp_list,osal_u8 * table,osal_u32 timestamp)1511 OAL_STATIC osal_u8 hmac_m2u_count_member_anysrclist(hmac_m2u_grp_list_entry_stru *grp_list, osal_u8 *table,
1512 osal_u32 timestamp)
1513 {
1514 hmac_m2u_grp_member_stru *grp_member;
1515 struct osal_list_head *grp_member_entry;
1516 osal_u8 count = 0;
1517 oal_bool_enum_uint8 ip_is_zero;
1518
1519 osal_list_for_each(grp_member_entry, &(grp_list->src_list)) {
1520 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
1521 hmac_m2u_grp_member_stru, member_entry);
1522 if (grp_member->src_ip_addr_len == OAL_IPV6_ADDR_SIZE) {
1523 ip_is_zero = (osal_u8)OAL_IPV6_IS_UNSPECIFIED_ADDR(grp_member->src_ip_addr);
1524 } else {
1525 ip_is_zero = (osal_u8)(*((osal_s32 *)(grp_member->src_ip_addr)) == 0);
1526 }
1527 if (ip_is_zero) {
1528 if (count > MAX_STA_NUM_OF_ONE_GROUP) {
1529 break;
1530 }
1531 oal_set_mac_addr(&table[count * WLAN_MAC_ADDR_LEN], grp_member->grp_member_mac);
1532 grp_member->timestamp = timestamp;
1533 count++;
1534 }
1535 }
1536 return (count);
1537 }
1538
1539 /*****************************************************************************
1540 函 数 名 : hmac_m2u_count_member_src_list
1541 功能描述 : 找出一个组播组内,组播源为指定源的所有STA用户
1542 输入参数 : grp_list 组播组结构体; src_ip_addr 组播源IP地址;
1543 table 组播组成员的MAC地址所在指针数组
1544 timestamp nowtime
1545 *****************************************************************************/
hmac_m2u_count_member_src_list(hmac_m2u_grp_list_entry_stru * grp_list,osal_u8 * src_ip_addr,osal_u8 * table,osal_u32 timestamp,osal_u8 count)1546 OAL_STATIC osal_u8 hmac_m2u_count_member_src_list(hmac_m2u_grp_list_entry_stru *grp_list,
1547 osal_u8 *src_ip_addr, osal_u8 *table, osal_u32 timestamp, osal_u8 count)
1548 {
1549 hmac_m2u_grp_member_stru *grp_member;
1550 struct osal_list_head *grp_member_entry;
1551 osal_u8 count_tmp = count;
1552
1553 if (count_tmp > MAX_STA_NUM_OF_ONE_GROUP) {
1554 return count_tmp;
1555 }
1556
1557 osal_list_for_each(grp_member_entry, &(grp_list->src_list)) {
1558 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
1559 hmac_m2u_grp_member_stru, member_entry);
1560 if (count_tmp > MAX_STA_NUM_OF_ONE_GROUP) {
1561 break;
1562 }
1563 /* 组播源地址符合,模式是inc,加入到输出的table中 */
1564 if (osal_memcmp(src_ip_addr, grp_member->src_ip_addr, grp_member->src_ip_addr_len) == 0) {
1565 if (grp_member->mode == HMAC_M2U_CMD_INCLUDE_LIST) {
1566 oal_set_mac_addr((osal_u8 *)(&table[count_tmp * WLAN_MAC_ADDR_LEN]),
1567 (const osal_u8 *)grp_member->grp_member_mac);
1568 grp_member->timestamp = timestamp;
1569 count_tmp++;
1570 }
1571 } else {
1572 /* 组播源未匹配,但模式为exc的情况也加入到输出table中 */
1573 if (grp_member->mode == HMAC_M2U_CMD_EXCLUDE_LIST) {
1574 oal_set_mac_addr((osal_u8 *)(&table[count_tmp * WLAN_MAC_ADDR_LEN]),
1575 (const osal_u8 *)grp_member->grp_member_mac);
1576 grp_member->timestamp = timestamp;
1577 count_tmp++;
1578 }
1579 }
1580 }
1581 return count_tmp;
1582 }
1583
1584 /*****************************************************************************
1585 函 数 名 : hmac_m2u_get_snooplist_member
1586 功能描述 : 找到一个group内需要该组播源的所有STA用户
1587 输入参数 : hmac_vap vap结构体;
1588 grp_addr 组播组mac地址;
1589 src_ip_addr 组播源IP地址;
1590 table 组播组成员的MAC地址所在指针数组
1591 mac_vlan_tag_stru *vlan_tag;//vlan结构体指针
1592 输出参数 : count
1593 *****************************************************************************/
hmac_m2u_get_snooplist_member(hmac_vap_stru * hmac_vap,osal_u8 * grp_addr,osal_u8 * src_ip_addr,osal_u8 * table,mac_vlan_tag_stru * vlan_tag)1594 OAL_STATIC osal_u8 hmac_m2u_get_snooplist_member(hmac_vap_stru *hmac_vap, osal_u8 *grp_addr,
1595 osal_u8 *src_ip_addr, osal_u8 *table, mac_vlan_tag_stru *vlan_tag)
1596 {
1597 hmac_m2u_grp_list_entry_stru *grp_list_member;
1598 osal_u8 count = 0;
1599 osal_u32 nowtime;
1600 hmac_m2u_list_update_stru list_entry;
1601
1602 memset_s(&list_entry, OAL_SIZEOF(hmac_m2u_list_update_stru), 0, OAL_SIZEOF(hmac_m2u_list_update_stru));
1603 if (memcpy_s(&(list_entry.grp_mac), OAL_SIZEOF(list_entry.grp_mac),
1604 grp_addr, WLAN_MAC_ADDR_LEN) != EOK) { // 存放vlan信息
1605 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_get_snooplist_member:memcpy addr fail", hmac_vap->vap_id);
1606 }
1607 if (vlan_tag != OAL_PTR_NULL) {
1608 if (memcpy_s(&(list_entry.outer_vlan_tag), OAL_SIZEOF(list_entry.outer_vlan_tag),
1609 vlan_tag, OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) { // 存放vlan信息
1610 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_get_snooplist_member:memcpy vlan fail", hmac_vap->vap_id);
1611 }
1612 }
1613
1614 nowtime = (osal_u32)oal_time_get_stamp_ms();
1615 grp_list_member = hmac_m2u_find_group_list(hmac_vap, &list_entry);
1616 if (grp_list_member != OAL_PTR_NULL) {
1617 count = hmac_m2u_count_member_anysrclist(grp_list_member, &table[0], nowtime);
1618 count = hmac_m2u_count_member_src_list(grp_list_member, src_ip_addr,
1619 &table[0], nowtime, count);
1620 oam_info_log3(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_get_snooplist_member::count is [%d] vlanId is [%d]}",
1621 hmac_vap->vap_id, count, grp_list_member->outer_vlan_tag.vlan_id);
1622 }
1623
1624 return (count);
1625 }
1626
1627 /*****************************************************************************
1628 函 数 名 : hmac_m2u_remove_node_grp
1629 功能描述 : 删除一个组播组下属于特定STA的节点,如果该入参STA为空,则清空该组播组
1630 输入参数 : grp_list 组播组结构体; hmac_user user结构体
1631 输出参数 : sta_num_removed 删除的sta个数
1632 *****************************************************************************/
hmac_m2u_remove_node_grp(hmac_m2u_grp_list_entry_stru * grp_list,const hmac_user_stru * hmac_user,osal_u8 * sta_num_removed)1633 OAL_STATIC osal_void hmac_m2u_remove_node_grp(hmac_m2u_grp_list_entry_stru *grp_list,
1634 const hmac_user_stru *hmac_user, osal_u8 *sta_num_removed)
1635 {
1636 hmac_m2u_grp_member_stru *grp_member;
1637 struct osal_list_head *grp_member_entry;
1638 struct osal_list_head *member_entry_temp;
1639 osal_u8 sta_count = 0;
1640
1641 osal_list_for_each_safe(grp_member_entry, member_entry_temp, &grp_list->src_list) {
1642 grp_member = (hmac_m2u_grp_member_stru *)osal_list_entry(grp_member_entry,
1643 hmac_m2u_grp_member_stru, member_entry);
1644 if ((hmac_user == grp_member->hmac_user) || (hmac_user == OAL_PTR_NULL)) {
1645 osal_list_del(&(grp_member->member_entry));
1646 oal_mem_free(grp_member, OAL_TRUE);
1647 sta_count++;
1648 }
1649 }
1650 if (grp_list->sta_num >= sta_count) {
1651 oam_warning_log2(0, OAM_SF_M2U, "{hmac_m2u_remove_node_grp::remove [%d] sta from a group with [%d] sta}",
1652 sta_count, grp_list->sta_num);
1653 grp_list->sta_num -= sta_count;
1654 } else {
1655 oam_error_log2(0, OAM_SF_M2U, "{hmac_m2u_remove_node_grp::fail to remove [%d] sta from a group with [%d] sta}",
1656 sta_count, grp_list->sta_num);
1657 grp_list->sta_num = 0;
1658 sta_count = grp_list->sta_num;
1659 }
1660 *sta_num_removed = sta_count;
1661 }
1662
1663 /*****************************************************************************
1664 函 数 名 : hmac_m2u_clean_snp_list
1665 功能描述 : 清空组播组链表以及组播组内的成员
1666 输入参数 : hmac_vap vap结构体
1667 *****************************************************************************/
hmac_m2u_clean_snp_list(hmac_vap_stru * hmac_vap)1668 OAL_STATIC osal_void hmac_m2u_clean_snp_list(hmac_vap_stru *hmac_vap)
1669 {
1670 osal_u8 sta_num_removed = 0;
1671 hmac_m2u_stru *m2u;
1672 hmac_m2u_snoop_list_stru *snp_list;
1673 hmac_m2u_grp_list_entry_stru *grp_list;
1674 struct osal_list_head *grp_list_entry;
1675 struct osal_list_head *grp_list_entry_temp;
1676
1677 /* 获取snoop链表头 */
1678 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
1679 snp_list = &(m2u->m2u_snooplist);
1680
1681 osal_list_for_each_safe(grp_list_entry, grp_list_entry_temp, &(snp_list->grp_list)) {
1682 grp_list = (hmac_m2u_grp_list_entry_stru *)osal_list_entry(grp_list_entry,
1683 hmac_m2u_grp_list_entry_stru, grp_entry);
1684
1685 hmac_m2u_remove_node_grp(grp_list, OAL_PTR_NULL, &sta_num_removed);
1686 osal_list_del(&(grp_list->grp_entry));
1687 oal_mem_free(grp_list, OAL_TRUE);
1688 grp_list = OAL_PTR_NULL;
1689 snp_list->group_list_count--;
1690 if (snp_list->total_sta_num >= sta_num_removed) {
1691 snp_list->total_sta_num -= sta_num_removed;
1692 oam_warning_log3(0, OAM_SF_M2U,
1693 "vap_id[%d] {hmac_m2u_clean_snp_list::remove a group with [%d] sta.current total sta num:[%d]}",
1694 hmac_vap->vap_id,
1695 sta_num_removed, snp_list->total_sta_num);
1696 } else {
1697 oam_error_log3(0, OAM_SF_M2U,
1698 "vap_id[%d] {hmac_m2u_clean_snp_list::remove a group with [%d] sta. but current total sta num is[%d]}",
1699 hmac_vap->vap_id, sta_num_removed, snp_list->total_sta_num);
1700 snp_list->total_sta_num = 0;
1701 }
1702 }
1703 }
1704
1705 /*****************************************************************************
1706 函 数 名 : hmac_m2u_cleanup_snoopwds_node
1707 功能描述 : 清空各个组播组内的某个STA用户
1708 输入参数 : hmac_user user结构体
1709 *****************************************************************************/
hmac_m2u_cleanup_snoopwds_node(hmac_user_stru * hmac_user)1710 osal_void hmac_m2u_cleanup_snoopwds_node(hmac_user_stru *hmac_user)
1711 {
1712 osal_u8 sta_num_removed = 0;
1713 hmac_vap_stru *hmac_vap;
1714 hmac_m2u_stru *m2u;
1715 hmac_m2u_snoop_list_stru *snp_list;
1716 hmac_m2u_grp_list_entry_stru *grp_list;
1717 struct osal_list_head *grp_list_entry;
1718 struct osal_list_head *grp_list_entry_temp;
1719
1720 hmac_vap = (hmac_vap_stru *)mac_res_get_hmac_vap(hmac_user->vap_id);
1721 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
1722 oam_info_log1(0, OAM_SF_ANY, "{hmac_m2u_cleanup_snoopwds_node::hmac_vap[id=%d] null!!}",
1723 hmac_user->vap_id);
1724 return;
1725 }
1726
1727 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
1728 snp_list = &(m2u->m2u_snooplist);
1729
1730 if ((hmac_vap->vap_mode == WLAN_VAP_MODE_BSS_AP) &&
1731 (snp_list != OAL_PTR_NULL) && (m2u->snoop_enable == OAL_TRUE)) {
1732 osal_list_for_each_safe(grp_list_entry, grp_list_entry_temp, &(snp_list->grp_list)) {
1733 grp_list = (hmac_m2u_grp_list_entry_stru *)osal_list_entry(grp_list_entry,
1734 hmac_m2u_grp_list_entry_stru, grp_entry);
1735 hmac_m2u_remove_node_grp(grp_list, hmac_user, &sta_num_removed);
1736 snp_list->total_sta_num -= sta_num_removed;
1737 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_cleanup_snoopwds_node::removed [%d] sta }",
1738 hmac_vap->vap_id, sta_num_removed);
1739 if (osal_list_empty(&(grp_list->src_list)) == OSAL_TRUE) { // 删除没有用户的组播组
1740 osal_list_del(&(grp_list->grp_entry));
1741 oal_mem_free(grp_list, OAL_TRUE);
1742 grp_list = OAL_PTR_NULL;
1743 snp_list->group_list_count--;
1744 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_cleanup_snoopwds_node::remove a null group }",
1745 hmac_vap->vap_id);
1746 }
1747 }
1748 }
1749 }
1750
1751 /*****************************************************************************
1752 函 数 名 : hmac_m2u_tx_event
1753 功能描述 : 组播转单播,单播封装802.11头以及发送事件
1754 输入参数 : hmac_vap vap结构体; user user结构体; buf netbuf结构体
1755 *****************************************************************************/
hmac_m2u_tx_event(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * buf)1756 OAL_STATIC osal_u32 hmac_m2u_tx_event(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, oal_netbuf_stru *buf)
1757 {
1758 osal_u32 ret;
1759
1760 /* 封装802.11头 */
1761 ret = hmac_tx_encap_etc(hmac_vap, hmac_user, buf);
1762 if (osal_unlikely(ret != OAL_SUCC)) {
1763 oam_warning_log2(0, OAM_SF_TX,
1764 "vap_id[%d] {hmac_tx_lan_mpdu_process_ap::hmac_tx_encap_etc failed[%d].}",
1765 hmac_vap->vap_id, ret);
1766 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_abnormal_msdu_dropped, 1);
1767 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, 1, OAL_PTR_NULL);
1768 return ret;
1769 }
1770 ret = hmac_tx_send_encap_data(hmac_vap, buf);
1771 if (osal_unlikely(ret != OAL_SUCC)) {
1772 oam_warning_log2(0, OAM_SF_TX, "vap_id[%d]{hmac_tx_lan_to_wlan_etc::frw_send_data failed[%d].}",
1773 hmac_vap->vap_id, ret);
1774 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_abnormal_msdu_dropped, 1);
1775 }
1776
1777 return ret;
1778 }
1779
1780 /*****************************************************************************
1781 函 数 名 : hmac_m2u_convert_loop_end
1782 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
1783 输出参数 : ul_ret
1784 *****************************************************************************/
hmac_m2u_convert_loop_end(oal_netbuf_stru * copy_buf,oal_netbuf_stru ** buf,osal_u8 * ucast_sta_cnt,osal_u8 * ucast_sta_idx)1785 OAL_STATIC osal_void hmac_m2u_convert_loop_end(oal_netbuf_stru *copy_buf, oal_netbuf_stru **buf,
1786 osal_u8 *ucast_sta_cnt, osal_u8 *ucast_sta_idx)
1787 {
1788 if (copy_buf != OAL_PTR_NULL) {
1789 *buf = copy_buf;
1790 copy_buf = OAL_PTR_NULL;
1791 }
1792 (*ucast_sta_idx)++;
1793 if (*ucast_sta_cnt > 0) {
1794 (*ucast_sta_cnt)--;
1795 }
1796 }
1797
1798 /*****************************************************************************
1799 函 数 名 : hmac_m2u_snoop_convert_count
1800 功能描述 : 组播转单播发送计数
1801 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
1802 输出参数 : ul_ret
1803 *****************************************************************************/
hmac_m2u_snoop_convert_count(hmac_vap_stru * hmac_vap,osal_u8 ucast_sta_cnt,osal_u32 ul_ret,oal_netbuf_stru * buf)1804 OAL_STATIC osal_void hmac_m2u_snoop_convert_count(hmac_vap_stru *hmac_vap, osal_u8 ucast_sta_cnt, osal_u32 ul_ret,
1805 oal_netbuf_stru *buf)
1806 {
1807 unref_param(hmac_vap);
1808 unref_param(ucast_sta_cnt);
1809 /* ucast event fail 的发送计数 */
1810 if (ul_ret != OAL_SUCC) {
1811 hmac_free_netbuf_list_etc(buf);
1812 }
1813 }
1814
1815 /*****************************************************************************
1816 函 数 名 : hmac_m2u_snoop_change_mac_hdr
1817 功能描述 : 组播转单播发送计数
1818 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
1819 输出参数 : ul_ret
1820 *****************************************************************************/
hmac_m2u_snoop_change_mac_hdr(const hmac_m2u_stru * m2u,mac_ether_header_stru ** ucast_ether_hdr,oal_netbuf_stru * buf)1821 OAL_STATIC osal_void hmac_m2u_snoop_change_mac_hdr(const hmac_m2u_stru *m2u, mac_ether_header_stru **ucast_ether_hdr,
1822 oal_netbuf_stru *buf)
1823 {
1824 mcast_tunnel_hdr_stru *mcast_tunhdr;
1825 mac_ether_header_stru *ether_hdr;
1826 osal_u8 srcmac[WLAN_MAC_ADDR_LEN];
1827
1828 ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(buf);
1829 oal_set_mac_addr((osal_u8 *)srcmac, (const osal_u8 *)ether_hdr->ether_shost);
1830 /* 加自定义tunnel协议 */
1831 if ((m2u->mcast_mode & BIT0) != 0) { /* mcast_mode = 1 */
1832 mcast_tunhdr = (mcast_tunnel_hdr_stru *) oal_netbuf_push(buf, OAL_SIZEOF(mcast_tunnel_hdr_stru));
1833 *ucast_ether_hdr = (mac_ether_header_stru *)oal_netbuf_push(buf, OAL_SIZEOF(mac_ether_header_stru));
1834 mcast_tunhdr->proto = MAC_ETH_PROTOCOL_SUBTYPE;
1835
1836 /* 拷贝原始组播源地址 */
1837 oal_set_mac_addr((osal_u8 *)(&((*ucast_ether_hdr)->ether_shost[0])), (const osal_u8 *)srcmac);
1838
1839 /* 拷贝新的协议类型 */
1840 (*ucast_ether_hdr)->ether_type = oal_host2net_short(ETHER_TUNNEL_TYPE);
1841 } else { /* 不加自定义tunnel协议 */ /* mcast_mode = 2 */
1842 *ucast_ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(buf);
1843 }
1844 }
1845
1846 /*****************************************************************************
1847 函 数 名 : hmac_m2u_group_is_special
1848 功能描述 : 所加入组播组的IP地址是否在特殊组播业务
1849 输入参数 : ether_data_type 以太网数据类型
1850 输出参数 : OAL_FALSE OR OAL_TRUE
1851 *****************************************************************************/
hmac_m2u_group_is_special(hmac_vap_stru * hmac_vap,osal_u16 ether_data_type,osal_u8 * ip_head)1852 OAL_STATIC osal_u32 hmac_m2u_group_is_special(hmac_vap_stru *hmac_vap, osal_u16 ether_data_type, osal_u8 *ip_head)
1853 {
1854 mac_ip_header_stru *ip_header;
1855 oal_ipv6hdr_stru *ipv6_hdr;
1856 hmac_m2u_snoop_list_stru *snp_list;
1857 osal_u8 idx;
1858 osal_u32 grp_addr;
1859 osal_u8 grp_ip_addr[OAL_IPV6_ADDR_SIZE] = {0};
1860 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
1861
1862 if (m2u == OAL_PTR_NULL) {
1863 return OAL_FALSE;
1864 }
1865 snp_list = &(m2u->m2u_snooplist);
1866
1867 if (ether_data_type == oal_host2net_short(ETHER_TYPE_IP)) {
1868 ip_header = (mac_ip_header_stru *)ip_head;
1869 grp_addr = oal_host2net_long(ip_header->daddr);
1870
1871 for (idx = 0; idx < SPECIAL_M2U_GROUP_COUNT_IPV4; idx++) {
1872 if (grp_addr == snp_list->special_group_ipv4[idx]) {
1873 return OAL_TRUE;
1874 }
1875 }
1876 }
1877
1878 if (ether_data_type == oal_host2net_short(ETHER_TYPE_IPV6)) {
1879 ipv6_hdr = (oal_ipv6hdr_stru *)(ip_head);
1880 if (memcpy_s(grp_ip_addr, OAL_SIZEOF(grp_ip_addr),
1881 (osal_s8 *)(&(ipv6_hdr->daddr)), OAL_IPV6_ADDR_SIZE) != EOK) {
1882 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_group_is_special:memcpy addr fail", hmac_vap->vap_id);
1883 }
1884 for (idx = 0; idx < SPECIAL_M2U_GROUP_COUNT_IPV6; idx++) {
1885 if (osal_memcmp(grp_ip_addr, snp_list->special_group_ipv6[idx], OAL_IPV6_ADDR_SIZE) == 0) {
1886 return OAL_TRUE;
1887 }
1888 }
1889 }
1890
1891 return OAL_FALSE;
1892 }
1893
hmac_m2u_sta_get_ready_user(hmac_user_stru * hmac_user_tmp,osal_u8 * srcmac,osal_u8 vap_id,osal_u8 ** dstmac,hmac_user_stru ** hmac_user)1894 OAL_STATIC osal_u32 hmac_m2u_sta_get_ready_user(hmac_user_stru *hmac_user_tmp, osal_u8 *srcmac,
1895 osal_u8 vap_id, osal_u8 **dstmac, hmac_user_stru **hmac_user)
1896 {
1897 if (hmac_user_tmp == OAL_PTR_NULL) {
1898 oam_error_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_sta_get_ready_user::user_tmp null.}", vap_id);
1899 return OSAL_FALSE;
1900 }
1901
1902 /* 如果用户尚未关联成功 */
1903 if (hmac_user_tmp->user_asoc_state != MAC_USER_STATE_ASSOC) {
1904 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_sta_get_ready_user::sta not assoc.}", vap_id);
1905 return OSAL_FALSE;
1906 }
1907
1908 *hmac_user = mac_res_get_hmac_user_etc(hmac_user_tmp->assoc_id);
1909 if (*hmac_user == OAL_PTR_NULL) {
1910 oam_error_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_sta_get_ready_user::hmac_user_tmp null.idx:%u}", vap_id,
1911 hmac_user_tmp->assoc_id);
1912 return OSAL_FALSE;
1913 }
1914
1915 *dstmac = hmac_user_tmp->user_mac_addr;
1916
1917 /* 发送的目的地址和发来的源地址相同的异常处理 */
1918 if (oal_compare_mac_addr(*dstmac, srcmac) == 0) {
1919 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_sta_get_ready_user::dstmac == srcmac.}", vap_id);
1920 return OSAL_FALSE;
1921 }
1922
1923 return OSAL_TRUE;
1924 }
1925
hmac_m2u_sta_fill_cb_and_mac_hdr(oal_netbuf_stru * netbuf,const hmac_user_stru * hmac_user,hmac_m2u_stru * m2u,osal_u8 * dstmac,mac_tx_ctl_stru ** tx_ctl_ret)1926 OAL_STATIC osal_void hmac_m2u_sta_fill_cb_and_mac_hdr(oal_netbuf_stru *netbuf, const hmac_user_stru *hmac_user,
1927 hmac_m2u_stru *m2u, osal_u8 *dstmac, mac_tx_ctl_stru **tx_ctl_ret)
1928 {
1929 mac_tx_ctl_stru *tx_ctl;
1930 mac_ether_header_stru *ucast_ether_hdr = OAL_PTR_NULL;
1931
1932 tx_ctl = (mac_tx_ctl_stru *)OAL_NETBUF_CB(netbuf);
1933 /* 组播转单播 CB字段处理 */
1934 mac_get_cb_is_mcast(tx_ctl) = OAL_FALSE;
1935 mac_get_cb_ack_polacy(tx_ctl) = WLAN_TX_NORMAL_ACK;
1936 mac_get_cb_tx_user_idx(tx_ctl) = (osal_u8)hmac_user->assoc_id;
1937 mac_get_cb_wme_tid_type(tx_ctl) = m2u->tid_num;
1938 mac_get_cb_wme_ac_type(tx_ctl) = wlan_wme_tid_to_ac(m2u->tid_num);
1939
1940 /* 组播转单播,mac头的封装 */
1941 hmac_m2u_snoop_change_mac_hdr(m2u, &ucast_ether_hdr, netbuf);
1942
1943 /* 将DA替换成关联设备的MAC */
1944 oal_set_mac_addr(&ucast_ether_hdr->ether_dhost[0], dstmac);
1945
1946 *tx_ctl_ret = tx_ctl;
1947 }
1948
1949 /*****************************************************************************
1950 函 数 名 : hmac_m2u_sta_convert
1951 功能描述 : 发送方向对所有下挂sta进行组播转单播处理
1952 输入参数 : hmac_vap vap结构体; buf netbuf 结构体; srcmac 源mac地址
1953 输出参数 : ul_ret
1954 *****************************************************************************/
hmac_m2u_sta_convert(hmac_vap_stru * hmac_vap,oal_netbuf_stru * buf,osal_u8 * srcmac,osal_u8 macaddr_len)1955 OAL_STATIC osal_u32 hmac_m2u_sta_convert(hmac_vap_stru *hmac_vap, oal_netbuf_stru *buf, osal_u8 *srcmac,
1956 osal_u8 macaddr_len)
1957 {
1958 hmac_user_stru *hmac_user = OAL_PTR_NULL;
1959 osal_u8 *dstmac = OAL_PTR_NULL;
1960 osal_u8 ucast_sta_cnt;
1961 osal_u8 ucast_sta_idx = 0;
1962
1963 oal_netbuf_stru *copy_buf = OAL_PTR_NULL;
1964 osal_u32 ul_ret;
1965 mac_tx_ctl_stru *tx_ctl = OAL_PTR_NULL;
1966 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
1967 struct osal_list_head *entry = OAL_PTR_NULL;
1968 struct osal_list_head *dlist_tmp = OAL_PTR_NULL;
1969 hmac_user_stru *hmac_user_tmp = OAL_PTR_NULL;
1970 osal_u32 free_buffer_cnt = 0 ;
1971
1972 unref_param(macaddr_len);
1973 ucast_sta_cnt = (osal_u8)hmac_vap->user_nums;
1974
1975 if (ucast_sta_cnt == 0) {
1976 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d]{hmac_m2u_sta_convert::no user associate this vap}", hmac_vap->vap_id);
1977 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
1978 return HMAC_TX_PASS;
1979 }
1980
1981 /* 遍历vap下所有用户 */
1982 osal_list_for_each_safe(entry, dlist_tmp, &(hmac_vap->mac_user_list_head)) {
1983 if (ucast_sta_cnt > 1) {
1984 copy_buf = oal_netbuf_copy(buf, GFP_ATOMIC);
1985 }
1986
1987 hmac_user_tmp = osal_list_entry(entry, hmac_user_stru, user_dlist);
1988 if (hmac_m2u_sta_get_ready_user(hmac_user_tmp, srcmac, hmac_vap->vap_id,
1989 &dstmac, &hmac_user) != OSAL_TRUE) {
1990 free_buffer_cnt = hmac_free_netbuf_list_etc(buf);
1991 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, free_buffer_cnt, OAL_PTR_NULL);
1992 /* 组播转单播发送循环的末尾处理 */
1993 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
1994 continue;
1995 }
1996
1997 hmac_m2u_sta_fill_cb_and_mac_hdr(buf, hmac_user_tmp, m2u, dstmac, &tx_ctl);
1998
1999 ul_ret = hmac_tx_ucast_process_etc(hmac_vap, buf, hmac_user, tx_ctl);
2000 if (osal_unlikely(ul_ret != HMAC_TX_PASS)) {
2001 if (ul_ret != HMAC_TX_BUFF) {
2002 /* 不等于HMAC_TX_BUFF,不缓存的直接释放 */
2003 oam_warning_log2(0, OAM_SF_M2U,
2004 "vap_id[%d] {hmac_m2u_sta_convert::hmac_tx_ucast_process_etc not pass or buff, ul_ret = [%d]}",
2005 hmac_vap->vap_id, ul_ret);
2006 free_buffer_cnt = hmac_free_netbuf_list_etc(buf);
2007 }
2008 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2009 continue;
2010 }
2011
2012 ul_ret = hmac_m2u_tx_event(hmac_vap, hmac_user, buf);
2013
2014 /* 组播转单播发送计数统计 */
2015 hmac_m2u_snoop_convert_count(hmac_vap, ucast_sta_cnt, ul_ret, buf);
2016
2017 /* 组播转单播发送循环的末尾处理 */
2018 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2019 }
2020
2021 return HMAC_TX_DONE;
2022 }
2023
2024 /*****************************************************************************
2025 函 数 名 : hmac_m2u_snoop_convert
2026 功能描述 : 发送方向的组播转单播处理
2027 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
2028 输出参数 : ul_ret
2029 *****************************************************************************/
hmac_m2u_snoop_convert(hmac_vap_stru * hmac_vap,oal_netbuf_stru * buf)2030 osal_u32 hmac_m2u_snoop_convert(hmac_vap_stru *hmac_vap, oal_netbuf_stru *buf)
2031 {
2032 hmac_user_stru *hmac_user = OAL_PTR_NULL;
2033 mac_ether_header_stru *ether_hdr;
2034 osal_u8 *dstmac;
2035 osal_u8 src_ip_addr[OAL_IPV6_ADDR_SIZE] = {0};
2036 osal_u8 dta_ip_addr[OAL_IPV6_ADDR_SIZE] = {0};
2037 osal_u32 grp_addr;
2038 osal_u8 srcmac[WLAN_MAC_ADDR_LEN];
2039 osal_u8 grpmac[WLAN_MAC_ADDR_LEN];
2040 osal_u8 empty_entry_mac[WLAN_MAC_ADDR_LEN] = {0};
2041 osal_u8 ucast_sta_mac[MAX_STA_NUM_OF_ONE_GROUP][WLAN_MAC_ADDR_LEN];
2042 osal_u8 ucast_sta_cnt;
2043 osal_u8 ucast_sta_idx = 0;
2044 mac_ether_header_stru *ucast_ether_hdr = OAL_PTR_NULL;
2045 oal_netbuf_stru *copy_buf = OAL_PTR_NULL;
2046 osal_u16 user_idx;
2047 osal_u16 ether_data_type;
2048 osal_u32 ul_ret;
2049 osal_u8 *ip_head;
2050 mac_tx_ctl_stru *tx_ctl;
2051 mac_ip_header_stru *ip_header;
2052 oal_ipv6hdr_stru *ipv6_hdr;
2053 mac_vlan_tag_stru *vlan_tag;
2054 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2055 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2056 hmac_m2u_grp_list_entry_stru *grp_list_member;
2057 hmac_m2u_list_update_stru list_entry;
2058 #endif
2059
2060 /* 未打开组转单播开关,发送原组播 */
2061 if (m2u->snoop_enable == OAL_FALSE) {
2062 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert::snoop is [%d] not enable}",
2063 hmac_vap->vap_id, m2u->snoop_enable);
2064 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2065 return HMAC_TX_PASS;
2066 }
2067 ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(buf);
2068 /* 带vlan tag 的情况 */
2069 if (ether_is_with_vlan_tag(ether_hdr->ether_type)) {
2070 // 偏移2个mac地址的长度,获取外层vlan tag
2071 vlan_tag = (mac_vlan_tag_stru *)(oal_netbuf_data(buf) + (ETHER_ADDR_LEN << 1));
2072 vlan_tag += 1;
2073 if (!ether_is_with_vlan_tag(vlan_tag->tpid)) { // 双层tag的情况,内层tag不考虑
2074 ether_data_type = *((osal_u16 *)vlan_tag); // 跳过tag后获取eth type
2075 ip_head = (osal_u8 *)vlan_tag + 2; // 2:跳过 type 和tag指向ip头起始地址
2076 } else {
2077 ether_data_type = *((osal_u16 *)(vlan_tag + 1)); // 跳过内层tag后获取eth type
2078 ip_head = (osal_u8 *)(vlan_tag + 1) + 2; // 2:跳过 type 和内层指向ip头起始地址
2079 }
2080 vlan_tag -= 1; // 指向外层tag,作为参数传递到下层
2081 } else { /* 非vlan 的情况 */
2082 ip_head = (osal_u8 *)(ether_hdr + 1);
2083 ether_data_type = ether_hdr->ether_type;
2084 vlan_tag = OAL_PTR_NULL;
2085 }
2086 oal_set_mac_addr((osal_u8 *)srcmac, (const osal_u8 *)ether_hdr->ether_shost);
2087 oal_set_mac_addr((osal_u8 *)grpmac, (const osal_u8 *)ether_hdr->ether_dhost);
2088
2089 /* 部分组播控制管理帧,进行组播转单播,发送给每一个关联STA */
2090 if (oal_is_mdnsv4_mac((osal_u8 *)ether_hdr, ether_data_type) ||
2091 oal_is_mdnsv6_mac((osal_u8 *)ether_hdr, ether_data_type) ||
2092 oal_is_icmpv6_proto(ether_data_type, ip_head) ||
2093 oal_is_igmp_proto(ether_data_type, ip_head) ||
2094 (hmac_m2u_group_is_special(hmac_vap, ether_data_type, ip_head) == OAL_TRUE)) {
2095 return hmac_m2u_sta_convert(hmac_vap, buf, srcmac, WLAN_MAC_ADDR_LEN);
2096 }
2097
2098 if (ether_data_type == oal_host2net_short(ETHER_TYPE_IP)) {
2099 ip_header = (mac_ip_header_stru *)ip_head;
2100 *((osal_u32 *)src_ip_addr) = ip_header->saddr;
2101 grp_addr = oal_host2net_long(ip_header->daddr);
2102 /* 该组在黑名单内,不进行组播转单播,组播处理 */
2103 if (hmac_m2u_snoop_is_denied_ipv4(hmac_vap, grp_addr) != 0) {
2104 oam_info_log3(0, OAM_SF_M2U, "{hmac_m2u_snoop_convert::group_addr[%02x].[%02x].[%02x].[xx] is denied}}",
2105 (osal_u32)((grp_addr >> 24) & 0xff), /* 24:偏移取值 */
2106 (osal_u32)((grp_addr >> 16) & 0xff), /* 16:偏移取值 */
2107 (osal_u32)((grp_addr >> 8) & 0xff)); /* 8:偏移取值 */
2108
2109 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2110 return HMAC_TX_PASS;
2111 }
2112 } else if (ether_data_type == oal_host2net_short(ETHER_TYPE_IPV6)) {
2113 ipv6_hdr = (oal_ipv6hdr_stru *)(ip_head);
2114 if (memcpy_s(src_ip_addr, OAL_SIZEOF(src_ip_addr),
2115 (osal_s8 *)(&(ipv6_hdr->saddr)), OAL_IPV6_ADDR_SIZE) != EOK) {
2116 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_snoop_convert:memcpy addr fail", hmac_vap->vap_id);
2117 }
2118
2119 if (memcpy_s(dta_ip_addr, OAL_SIZEOF(dta_ip_addr),
2120 (osal_s8 *)(&(ipv6_hdr->daddr)), OAL_IPV6_ADDR_SIZE) != EOK) {
2121 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_snoop_convert:memcpy dta addr fail", hmac_vap->vap_id);
2122 }
2123 if (hmac_m2u_snoop_is_denied_ipv6(hmac_vap, (osal_u8 *)dta_ip_addr) != 0) {
2124 oam_info_log1(0, OAM_SF_M2U,
2125 "{hmac_m2u_snoop_convert::group_addr_IPV6 \
2126 [%08x]:[xxxxxxxx]:[xxxxxxxx]:[xxxxxxxx] is denied}}", \
2127 oal_host2net_long(*(osal_u32 *)(&dta_ip_addr[0])));
2128 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2129 return HMAC_TX_PASS;
2130 }
2131 } else {
2132 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2133 return HMAC_TX_PASS;
2134 }
2135
2136 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2137 memset_s(&list_entry, OAL_SIZEOF(hmac_m2u_list_update_stru), 0, OAL_SIZEOF(hmac_m2u_list_update_stru));
2138 if (memcpy_s(&(list_entry.grp_mac), OAL_SIZEOF(list_entry.grp_mac), grpmac, WLAN_MAC_ADDR_LEN) != EOK) {
2139 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_snoop_convert::memcpy addr fail", hmac_vap->vap_id);
2140 }
2141 if (vlan_tag != OAL_PTR_NULL) {
2142 if (memcpy_s(&(list_entry.outer_vlan_tag), OAL_SIZEOF(list_entry.outer_vlan_tag),
2143 vlan_tag, OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) {
2144 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_snoop_convert::memcpy vlan fail", hmac_vap->vap_id);
2145 }
2146 }
2147 grp_list_member = hmac_m2u_find_group_list(hmac_vap, &list_entry);
2148 /* 组播snoop表中不存在当前组播帧所在的组播组,组播转发处理 */
2149 if (grp_list_member == OAL_PTR_NULL_member) {
2150 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert:: grp_list_member is null}",
2151 hmac_vap->vap_id);
2152 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2153 return HMAC_TX_PASS;
2154 }
2155 #endif
2156 ucast_sta_cnt = hmac_m2u_get_snooplist_member(hmac_vap, (osal_u8 *)grpmac, (osal_u8 *)src_ip_addr,
2157 ucast_sta_mac[0], vlan_tag); // 找出接收该组播的 sta 个数及他们的mac
2158 /* 如果没有STA需要此netbuf,不进行组播转单播处理 */
2159 if (ucast_sta_cnt == 0) {
2160 oam_info_log1(0, OAM_SF_M2U, "vap[%d] {hmac_m2u_snoop_convert::no user need this packet}", hmac_vap->vap_id);
2161 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2162 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2163 // 直接丢弃ipv6包会导致ipv6 ping包失败,由HMAC_TX_DROP_MTOU_FAIL改为HMAC_TX_PASS
2164 if (oal_host2net_short(ETHER_TYPE_IPV6) != ether_data_type) {
2165 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, 1, buf);
2166 return HMAC_TX_DROP_MTOU_FAIL;
2167 }
2168 #endif
2169 return HMAC_TX_PASS;
2170 }
2171
2172 /* 如果有用户需要该netbuf,但不需要组播转单播,直接发送原组播 */
2173 if (m2u->mcast_mode == HMAC_M2U_MCAST_MAITAIN) { /* mcast_mode = 0 */
2174 oam_info_log3(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert:: %d user found , mcast mode is %d}",
2175 hmac_vap->vap_id, ucast_sta_cnt, m2u->mcast_mode);
2176 OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_m2u_mcast_cnt, 1);
2177 return HMAC_TX_PASS;
2178 }
2179
2180 tx_ctl = (mac_tx_ctl_stru *)OAL_NETBUF_CB(buf);
2181
2182 /* 组播转单播 CB字段处理 */
2183 mac_get_cb_is_mcast(tx_ctl) = OAL_FALSE;
2184 mac_get_cb_ack_polacy(tx_ctl) = WLAN_TX_NORMAL_ACK;
2185 mac_get_cb_tx_user_idx(tx_ctl) = MAC_INVALID_USER_ID;
2186 mac_get_cb_wme_tid_type(tx_ctl) = m2u->tid_num;
2187 mac_get_cb_wme_ac_type(tx_ctl) = wlan_wme_tid_to_ac(m2u->tid_num);
2188 do {
2189 dstmac = &ucast_sta_mac[ucast_sta_idx][0];
2190 tx_ctl = (mac_tx_ctl_stru *)OAL_NETBUF_CB(buf);
2191
2192 if (ucast_sta_cnt > 1) {
2193 copy_buf = oal_netbuf_copy(buf, GFP_ATOMIC);
2194 }
2195
2196 /* 发送的目的地址和发来的源地址相同的异常处理 */
2197 if (oal_compare_mac_addr(dstmac, (const osal_u8 *)srcmac) == 0) {
2198 hmac_free_netbuf_list_etc(buf);
2199 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert::dstmac == srcmac.}",
2200 hmac_vap->vap_id);
2201
2202 /* 组播转单播发送循环的末尾处理 */
2203 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2204 continue;
2205 }
2206
2207 /* 如果接收端的STA的地址为空,则说明至少有一个STA加入到这个组后又离开了 */
2208 /* 这样的情况需要丢弃该帧 */
2209 if (oal_compare_mac_addr(dstmac, (const osal_u8 *)empty_entry_mac) == 0) {
2210 oam_info_log3(0, OAM_SF_M2U,
2211 "vap_id[%d] {hmac_m2u_snoop_convert::dstmac == NULL && ucast_sta_cnt is %d && discard mcast is %d}",
2212 hmac_vap->vap_id, ucast_sta_cnt, m2u->discard_mcast);
2213 if ((ucast_sta_cnt > 1) || (m2u->discard_mcast == OAL_TRUE)) {
2214 hmac_free_netbuf_list_etc(buf);
2215 /* 组播转单播发送循环的末尾处理 */
2216 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2217 continue;
2218 } else { /* 如果只有一个地址为空的STA用户,将该MAC地址还原成组播组的MAC地址 */
2219 ucast_sta_cnt = 0;
2220 dstmac = ether_hdr->ether_dhost;
2221
2222 /* 组播CB字段处理 */
2223 mac_get_cb_is_mcast(tx_ctl) = OAL_TRUE;
2224 mac_get_cb_ack_polacy(tx_ctl) = WLAN_TX_NO_ACK;
2225 mac_get_cb_wme_tid_type(tx_ctl) = WLAN_TIDNO_BCAST;
2226 mac_get_cb_wme_ac_type(tx_ctl) = wlan_wme_tid_to_ac(WLAN_TIDNO_BCAST);
2227 }
2228 }
2229
2230 /* 组播用户的查找 */
2231 if ((ETHER_IS_MULTICAST(dstmac) != 0) && (!ETHER_IS_BROADCAST(dstmac))) {
2232 user_idx = hmac_vap->multi_user_idx;
2233 ul_ret = HMAC_TX_PASS;
2234 } else { /* 组播转单播用户的查找 */
2235 ul_ret = hmac_vap_find_user_by_macaddr_etc(hmac_vap, dstmac, &user_idx);
2236 }
2237
2238 /* 用户未找到,丢弃该帧 */
2239 if (osal_unlikely(ul_ret != OAL_SUCC)) {
2240 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert::find user fail[%d].}",
2241 hmac_vap->vap_id, ul_ret);
2242 hmac_free_netbuf_list_etc(buf);
2243 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2244 continue;
2245 }
2246
2247 /* 转成HMAC的USER结构体 */
2248 hmac_user = (hmac_user_stru *)mac_res_get_hmac_user_etc(user_idx);
2249 if (osal_unlikely(hmac_user == OAL_PTR_NULL)) {
2250 oam_warning_log1(0, OAM_SF_CFG, "{hmac_m2u_snoop_convert::null param,user[%d].}", user_idx);
2251 hmac_free_netbuf_list_etc(buf);
2252 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2253 continue;
2254 }
2255 /* 用户状态判断 */
2256 if (osal_unlikely(hmac_user->user_asoc_state != MAC_USER_STATE_ASSOC)) {
2257 if (ucast_sta_cnt > 0) {
2258 hmac_m2u_cleanup_snoopwds_node(hmac_user);
2259 }
2260 /* 发送失败计数 */
2261 hmac_m2u_snoop_convert_count(hmac_vap, ucast_sta_cnt, OAL_FAIL, buf);
2262 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert::asoc state is [%d].}",
2263 hmac_vap->vap_id, hmac_user->user_asoc_state);
2264 /* 组播转单播发送循环的末尾处理 */
2265 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2266 continue;
2267 }
2268
2269 /* 目标user指针 */
2270 mac_get_cb_tx_user_idx(tx_ctl) = (osal_u8)user_idx;
2271
2272 if (ucast_sta_cnt <= 0) {
2273 /* 组播转单播,单播以太网头的封装 */
2274 ul_ret = hmac_m2u_tx_event(hmac_vap, hmac_user, buf);
2275
2276 /* 组播转单播发送计数统计 */
2277 hmac_m2u_snoop_convert_count(hmac_vap, ucast_sta_cnt, ul_ret, buf);
2278
2279 /* 组播转单播发送循环的末尾处理 */
2280 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2281 continue;
2282 }
2283
2284 /* 组播转单播,mac头的封装 */
2285 hmac_m2u_snoop_change_mac_hdr(m2u, &ucast_ether_hdr, buf);
2286 #ifdef _PRE_WLAN_FEATURE_VIRTUAL_MULTI_STA
2287 if (OAL_TRUE == hmac_user->is_wds) {
2288 hmac_vap_stru *hmac_vap_tmp;
2289 hmac_wds_stas_stru *sta = OAL_PTR_NULL;
2290 hmac_vap_tmp = (hmac_vap_stru *)mac_res_get_hmac_vap(hmac_user->vap_id);
2291 /* 发送目的地址对应的sta挂在当前repeater下 */
2292 if (hmac_wds_find_sta(hmac_vap_tmp, (osal_u8 *)(&srcmac[0]), &sta) == OAL_SUCC) {
2293 hmac_free_netbuf_list_etc(buf);
2294 oam_info_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_snoop_convert::sta in wds tables.}",
2295 hmac_vap->vap_id);
2296 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2297 continue;
2298 }
2299 } else {
2300 oal_set_mac_addr((osal_u8 *)(&ucast_ether_hdr->ether_dhost[0]), &ucast_sta_mac[ucast_sta_idx][0]);
2301 }
2302 #else
2303 {
2304 oal_set_mac_addr((osal_u8 *)(&ucast_ether_hdr->ether_dhost[0]), &ucast_sta_mac[ucast_sta_idx][0]);
2305 }
2306 #endif
2307 tx_ctl->is_m2u_data = OSAL_TRUE;
2308 ul_ret = hmac_tx_ucast_process_etc(hmac_vap, buf, hmac_user, tx_ctl);
2309 if (osal_unlikely(ul_ret != HMAC_TX_PASS)) {
2310 if (ul_ret != HMAC_TX_BUFF) {
2311 /* 不等于HMAC_TX_BUFF,不缓存的直接释放 */
2312 oam_warning_log2(0, OAM_SF_M2U,
2313 "vap_id[%d]{hmac_m2u_snoop_convert::hmac_tx_ucast_process_etc not pass or buff, ul_ret = [%d]}",
2314 hmac_vap->vap_id, ul_ret);
2315 hmac_free_netbuf_list_etc(buf);
2316 }
2317
2318 /* 组播转单播发送循环的末尾处理 */
2319 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2320 continue;
2321 }
2322
2323 ul_ret = hmac_m2u_tx_event(hmac_vap, hmac_user, buf);
2324
2325 /* 组播转单播发送计数统计 */
2326 hmac_m2u_snoop_convert_count(hmac_vap, ucast_sta_cnt, ul_ret, buf);
2327
2328 /* 组播转单播发送循环的末尾处理 */
2329 hmac_m2u_convert_loop_end(copy_buf, &buf, &ucast_sta_cnt, &ucast_sta_idx);
2330 } while ((ucast_sta_cnt > 0) && (m2u->snoop_enable == OAL_TRUE));
2331 return HMAC_TX_DONE;
2332 }
2333
2334 /*****************************************************************************
2335 函 数 名 : hmac_m2u_snoop_list_init
2336 功能描述 : 发送方向的组播转单播处理
2337 输入参数 : hmac_vap vap结构体
2338 *****************************************************************************/
hmac_m2u_snoop_list_init(hmac_vap_stru * hmac_vap)2339 OAL_STATIC osal_void hmac_m2u_snoop_list_init(hmac_vap_stru *hmac_vap)
2340 {
2341 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2342 hmac_m2u_snoop_list_stru *snp_list = &(m2u->m2u_snooplist);
2343
2344 snp_list->group_list_count = 0;
2345 snp_list->total_sta_num = 0;
2346 snp_list->misc = 0;
2347 OSAL_INIT_LIST_HEAD(&(snp_list->grp_list));
2348 }
2349
2350 /*****************************************************************************
2351 函 数 名 : hmac_m2u_unicast_convert_multicast
2352 功能描述 : 接收方向的单播转组播处理
2353 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
2354 输出参数 : ul_ret
2355 *****************************************************************************/
hmac_m2u_unicast_convert_multicast(hmac_vap_stru * hmac_vap,oal_netbuf_stru * pst_netbuf,hmac_msdu_stru * msdu)2356 WIFI_TCM_TEXT osal_void hmac_m2u_unicast_convert_multicast(hmac_vap_stru *hmac_vap, oal_netbuf_stru *pst_netbuf,
2357 hmac_msdu_stru *msdu)
2358 {
2359 mac_llc_snap_stru *snap;
2360 mac_vlan_tag_stru *vlan_tag;
2361 osal_u16 ether_type;
2362 osal_u16 ether_data_type;
2363 osal_u8 *ip_head;
2364 oal_ipv6hdr_stru *ipv6_hdr;
2365 mac_ip_header_stru *ip_header;
2366
2367 /* pst_netbuf未转化为以太网格式的帧,此时只有8个字节的snap头空间 */
2368 snap = (mac_llc_snap_stru *)oal_netbuf_data(pst_netbuf);
2369 ether_type = snap->ether_type;
2370
2371 /* 带vlan tag 的情况 */
2372 if (!ether_is_with_vlan_tag(ether_type)) {
2373 /* 非vlan 的情况 */
2374 ip_head = (osal_u8 *)(oal_netbuf_data(pst_netbuf) + ETHER_ADDR_LEN + 2); // 2:偏移8个字节长度的snap头空间
2375 ether_data_type = *((osal_u16 *)(oal_netbuf_data(pst_netbuf) + ETHER_ADDR_LEN));
2376 vlan_tag = OAL_PTR_NULL;
2377 } else {
2378 vlan_tag = (mac_vlan_tag_stru *)(oal_netbuf_data(pst_netbuf) +
2379 ETHER_ADDR_LEN); // 偏移1个mac地址的长度,获取外层vlan tag
2380 vlan_tag += 1;
2381 if (ether_is_with_vlan_tag(vlan_tag->tpid)) { // 双层tag的情况,内层tag不考虑
2382 ether_data_type = *((osal_u16 *)(vlan_tag + 1)); // 跳过内层tag后获取eth type
2383 ip_head = (osal_u8 *)(vlan_tag + 1) + 2; // 2:跳过 type 和内层指向ip头起始地址
2384 } else {
2385 ether_data_type = *((osal_u16 *)vlan_tag); // 跳过tag后获取eth type
2386 ip_head = (osal_u8 *)vlan_tag + 2; // 2:跳过 type 和tag指向ip头起始地址
2387 }
2388 vlan_tag -= 1; // 指向外层tag,作为参数传递到下层
2389 }
2390
2391 if (ether_data_type == oal_host2net_short(ETHER_TYPE_IP)) {
2392 ip_header = (mac_ip_header_stru *)ip_head;
2393
2394 if (oal_ipv4_is_multicast((osal_u8 *)(&(ip_header->daddr)))) {
2395 /* 根据组播ip还原mac */
2396 hmac_m2u_get_group_mac(msdu->da, (osal_u8 *)(&(ip_header->daddr)), OAL_IPV4_ADDR_SIZE);
2397 oam_info_log4(0, OAM_SF_M2U,
2398 "ipv4 group addr = [%02x]:[%02x]:[%02x]:[%02x]:[xx]:[xx]",
2399 msdu->da[0], msdu->da[1], msdu->da[2], msdu->da[3]); /* 打印 0 1 2 3 位mac */
2400 }
2401 } else if (ether_data_type == oal_host2net_short(ETHER_TYPE_IPV6)) {
2402 ipv6_hdr = (oal_ipv6hdr_stru *)(ip_head);
2403
2404 if (oal_ipv6_is_multicast(ipv6_hdr->daddr.in6_u.u6_addr8) != 0) {
2405 hmac_m2u_get_group_mac(msdu->da, ipv6_hdr->daddr.in6_u.u6_addr8, OAL_IPV6_ADDR_SIZE);
2406 oam_info_log4(0, OAM_SF_M2U,
2407 "ipv6 group mac = [%02x]:[%02x]:[%02x]:[%02x]:[xx]:[xx]",
2408 msdu->da[0], msdu->da[1], msdu->da[2], msdu->da[3]); /* 打印 0 1 2 3 位mac */
2409 }
2410 } else {
2411 oam_info_log2(0, OAM_SF_M2U,
2412 "vap_id[%d] {hmac_m2u_unicast_convert_multicast::ether type is not IP Protocol.[0x%x]}",
2413 hmac_vap->vap_id, oal_host2net_short(ether_data_type));
2414 return;
2415 }
2416 }
2417
2418 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2419 /*****************************************************************************
2420 函 数 名 : hmac_m2u_adaptive_list_init
2421 功能描述 : 配网模式初始化设置
2422 输入参数 : hmac_vap vap结构体
2423 输出参数 : 无
2424 *****************************************************************************/
hmac_m2u_adaptive_list_init(hmac_vap_stru * hmac_vap)2425 osal_void hmac_m2u_adaptive_list_init(hmac_vap_stru *hmac_vap)
2426 {
2427 osal_u32 loop;
2428 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2429
2430 /* 初始化链表 */
2431 for (loop = 0; loop < HMAC_M2U_ADAPTIVE_STA_HASHSIZE; loop++) {
2432 OSAL_INIT_LIST_HEAD(&(m2u->m2u_adaptive_hash[loop]));
2433 }
2434 m2u->adaptive_sta_count = 0;
2435 }
2436
2437 /*****************************************************************************
2438 函 数 名 : hmac_m2u_clean_adaptive_list
2439 功能描述 : 清空配网STA链表
2440 输入参数 : hmac_vap vap结构体
2441 输出参数 : 无
2442 *****************************************************************************/
hmac_m2u_clean_adaptive_list(hmac_vap_stru * hmac_vap)2443 OAL_STATIC osal_void hmac_m2u_clean_adaptive_list(hmac_vap_stru *hmac_vap)
2444 {
2445 hmac_m2u_stru *m2u;
2446 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2447 struct osal_list_head *sta_list_entry;
2448 struct osal_list_head *sta_list_entry_temp;
2449 osal_u32 loop;
2450
2451 /* 获取配网STA链表头 */
2452 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2453
2454 /* 删除链表 */
2455 for (loop = 0; loop < HMAC_M2U_ADAPTIVE_STA_HASHSIZE; loop++) {
2456 osal_list_for_each_safe(sta_list_entry, sta_list_entry_temp,
2457 &(m2u->m2u_adaptive_hash[loop])) {
2458 hash_adaptive = osal_list_entry(sta_list_entry, hmac_m2u_adaptive_hash_stru, adaptive_entry);
2459 osal_list_del(sta_list_entry);
2460 oal_mem_free(hash_adaptive, OAL_TRUE);
2461 }
2462 }
2463 m2u->adaptive_sta_count = 0;
2464 }
2465
2466 /*****************************************************************************
2467 函 数 名 : hmac_m2u_find_adaptive_list
2468 功能描述 : 根据配网设备的mac地址返回所需的组
2469 输入参数 : hmac_vap vap结构体; hmac_m2u_adaptive_list_update_stru *adaptive_list_entry待查找组播组信息
2470 输出参数 : adaptive_list_member 组播组结构体 OR 空指针
2471 *****************************************************************************/
hmac_m2u_find_adaptive_list(hmac_vap_stru * hmac_vap,mac_m2u_adaptive_list_update_stru * adaptive_list_entry)2472 OAL_STATIC hmac_m2u_adaptive_hash_stru *hmac_m2u_find_adaptive_list(hmac_vap_stru *hmac_vap,
2473 mac_m2u_adaptive_list_update_stru *adaptive_list_entry)
2474 {
2475 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2476 struct osal_list_head *sta_list_entry;
2477 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2478 osal_u8 hash;
2479
2480 if (m2u == OAL_PTR_NULL) {
2481 return OAL_PTR_NULL;
2482 }
2483
2484 /* 获取HASH桶值 以及HASH链表 */
2485 hash = (osal_u8)hmac_adaptive_cal_hash_value(adaptive_list_entry->new_member_mac);
2486
2487 /* 遍历配网STA组链表,找到地址匹配的配网STA */
2488 osal_list_for_each(sta_list_entry, &(m2u->m2u_adaptive_hash[hash])) {
2489 hash_adaptive = osal_list_entry(sta_list_entry, hmac_m2u_adaptive_hash_stru, adaptive_entry);
2490 if ((!oal_compare_mac_addr(adaptive_list_entry->new_member_mac, hash_adaptive->adaptive_mac)) &&
2491 (!osal_memcmp(&(adaptive_list_entry->outer_vlan_tag), &(hash_adaptive->outer_vlan_tag),
2492 OAL_SIZEOF(mac_vlan_tag_stru)))) {
2493 return hash_adaptive;
2494 }
2495 }
2496
2497 return OAL_PTR_NULL;
2498 }
2499
2500 /*****************************************************************************
2501 函 数 名 : hmac_m2u_create_adaptive_list
2502 功能描述 : 根据配网STA的MAC地址创建一个组,如果此组存在则返回该组,否则重新创建
2503 输入参数 : hmac_vap vap结构体; hmac_m2u_adaptive_list_update_stru *list_entry,待 操作节点信息
2504 输出参数 : adaptive_list_member 配网STA结构体
2505 *****************************************************************************/
hmac_m2u_create_adaptive_list(hmac_vap_stru * hmac_vap,hmac_m2u_adaptive_list_update_stru * adaptive_list_entry)2506 OAL_STATIC hmac_m2u_adaptive_hash_stru *hmac_m2u_create_adaptive_list(hmac_vap_stru *hmac_vap,
2507 hmac_m2u_adaptive_list_update_stru *adaptive_list_entry)
2508 {
2509 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2510 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2511 osal_u8 hash;
2512
2513 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
2514 return hash_adaptive;
2515 }
2516
2517 /* 获取HASH桶值 以及HASH链表 */
2518 hash = (osal_u8)hmac_adaptive_cal_hash_value(adaptive_list_entry->new_member_mac);
2519
2520 hash_adaptive = hmac_m2u_find_adaptive_list(hmac_vap, adaptive_list_entry);
2521 if (hash_adaptive == OAL_PTR_NULL) {
2522 if (m2u->adaptive_sta_count >= MAX_STA_NUM_OF_ADAPTIVE) {
2523 oam_warning_log2(0, OAM_SF_M2U,
2524 "vap_id[%d] {hmac_m2u_create_adaptive_list::m2u->adaptive_sta_count is [%d].}",
2525 hmac_vap->vap_id, m2u->adaptive_sta_count);
2526 return OAL_PTR_NULL;
2527 }
2528 hash_adaptive = oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, OAL_SIZEOF(hmac_m2u_adaptive_hash_stru), OAL_TRUE);
2529 if (osal_unlikely(hash_adaptive == OAL_PTR_NULL)) {
2530 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_create_adaptive_list::hash_adaptive_new null.}",
2531 hmac_vap->vap_id);
2532 return hash_adaptive;
2533 }
2534
2535 memset_s(hash_adaptive, OAL_SIZEOF(hmac_m2u_adaptive_hash_stru), 0x0, OAL_SIZEOF(hmac_m2u_adaptive_hash_stru));
2536 if (memcpy_s(&(hash_adaptive->outer_vlan_tag), OAL_SIZEOF(hash_adaptive->outer_vlan_tag),
2537 &(adaptive_list_entry->outer_vlan_tag), OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) {
2538 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_create_adaptive_list::memcpy vlan fail", hmac_vap->vap_id);
2539 }
2540 oal_set_mac_addr((osal_u8 *)hash_adaptive->adaptive_mac, (const osal_u8 *)adaptive_list_entry->new_member_mac);
2541 hash_adaptive->m2u_adaptive = OAL_FALSE;
2542 hash_adaptive->timestamp = adaptive_list_entry->timestamp;
2543 hash_adaptive->adaptive_num = 1;
2544 osal_list_add_tail(&(hash_adaptive->adaptive_entry), &(m2u->m2u_adaptive_hash[hash]));
2545 m2u->adaptive_sta_count++;
2546
2547 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_create_adaptive_list::create a new group.group num:[%d]}",
2548 hmac_vap->vap_id, m2u->adaptive_sta_count);
2549 }
2550
2551 return hash_adaptive;
2552 }
2553
2554 /*****************************************************************************
2555 功能描述 : 获取外层vlan tag
2556 *****************************************************************************/
hmac_m2u_adaptive_inspecting_get_vlan(hmac_vap_stru * hmac_vap,hmac_m2u_adaptive_list_update_stru * adaptive_list_entry,const mac_vlan_tag_stru * vlan_tag)2557 OAL_STATIC osal_void hmac_m2u_adaptive_inspecting_get_vlan(hmac_vap_stru *hmac_vap,
2558 hmac_m2u_adaptive_list_update_stru *adaptive_list_entry, const mac_vlan_tag_stru *vlan_tag)
2559 {
2560 if (memcpy_s(&(adaptive_list_entry->outer_vlan_tag), OAL_SIZEOF(adaptive_list_entry->outer_vlan_tag),
2561 vlan_tag, OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) {
2562 oam_warning_log1(0, OAM_SF_M2U, "vap[%d] hmac_m2u_adaptive_inspecting_get_vlan:memcpy fail", hmac_vap->vap_id);
2563 }
2564 }
2565
2566 /*****************************************************************************
2567 函 数 名 : hmac_m2u_adaptive_inspecting
2568 功能描述 : 监听配网组播报文来创建配网STA链表
2569 输入参数 : hmac_vap vap结构体; buf netbuf结构体
2570 输出参数 : 无
2571 *****************************************************************************/
hmac_m2u_adaptive_inspecting(hmac_vap_stru * hmac_vap,oal_netbuf_stru * buf)2572 osal_void hmac_m2u_adaptive_inspecting(hmac_vap_stru *hmac_vap, oal_netbuf_stru *buf)
2573 {
2574 mac_ether_header_stru *ether_header = (mac_ether_header_stru *)oal_netbuf_data(buf);
2575 /* source address which send the report and it is the member */
2576 osal_u8 *src_addr = ether_header->ether_shost;
2577 /* list entry where all member details will be updated and passed on updating the adaptive list */
2578 hmac_m2u_adaptive_list_update_stru adaptive_list_entry;
2579 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2580 hmac_m2u_stru *m2u = OAL_PTR_NULL;
2581 mac_vlan_tag_stru *vlan_tag = OAL_PTR_NULL;
2582
2583 memset_s(&adaptive_list_entry, OAL_SIZEOF(adaptive_list_entry), 0, OAL_SIZEOF(adaptive_list_entry));
2584 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2585 if (OAL_FALSE == m2u->adaptive_enable || OAL_FALSE == m2u->snoop_enable) {
2586 oam_info_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_adaptive_inspecting::adaptive is [%d] not enable}",
2587 hmac_vap->vap_id, m2u->frequency_enable);
2588 return;
2589 }
2590
2591 /* 获取以太网头 */
2592 oal_set_mac_addr(adaptive_list_entry.new_member_mac, src_addr);
2593 adaptive_list_entry.hmac_vap = hmac_vap;
2594 adaptive_list_entry.timestamp = (osal_u32)oal_time_get_stamp_ms();
2595
2596 /* 带vlan tag 的情况 */
2597 if (ether_is_with_vlan_tag(ether_header->ether_type)) {
2598 // 偏移2个mac地址的长度,获取外层vlan tag
2599 vlan_tag = (mac_vlan_tag_stru *)(oal_netbuf_data(buf) + (ETHER_ADDR_LEN << 1));
2600 hmac_m2u_adaptive_inspecting_get_vlan(hmac_vap, &adaptive_list_entry, vlan_tag);
2601
2602 vlan_tag += 1; // 判断内层tag
2603 if (ether_is_with_vlan_tag(vlan_tag->tpid)) {
2604 vlan_tag += 1; // 不考虑内层tag,跳过
2605 }
2606 } else { /* 非vlan 的情况 */
2607 vlan_tag = OAL_PTR_NULL;
2608 }
2609
2610 hash_adaptive = hmac_m2u_find_adaptive_list(hmac_vap, &adaptive_list_entry);
2611 if (hash_adaptive == OAL_PTR_NULL) {
2612 hash_adaptive = hmac_m2u_create_adaptive_list(hmac_vap, &adaptive_list_entry);
2613 if (osal_unlikely(hash_adaptive == OAL_PTR_NULL)) {
2614 oam_warning_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_adaptive_inspecting::list null.}", hmac_vap->vap_id);
2615 return;
2616 }
2617 } else {
2618 if (oal_time_get_runtime((hash_adaptive->timestamp), (adaptive_list_entry.timestamp)) > (m2u->threshold_time)) {
2619 hash_adaptive->adaptive_num = 1;
2620 hash_adaptive->timestamp = adaptive_list_entry.timestamp;
2621 hash_adaptive->m2u_adaptive = OAL_FALSE;
2622 } else {
2623 hash_adaptive->timestamp = adaptive_list_entry.timestamp;
2624 hash_adaptive->adaptive_num++;
2625 if (hash_adaptive->adaptive_num >= (m2u->adaptive_num)) {
2626 hash_adaptive->m2u_adaptive = OAL_TRUE;
2627 hash_adaptive->adaptive_num = m2u->adaptive_num;
2628 }
2629 }
2630 }
2631 }
2632
2633 /*****************************************************************************
2634 函 数 名 : hmac_m2u_sa_is_hwsmart
2635 功能描述 : 组播报文是否属于hw智能家居单品
2636 输入参数 : ip_header ipv4头结构体
2637 输出参数 : OAL_FALSE OR OAL_TRUE
2638 *****************************************************************************/
hmac_m2u_sa_is_hwsmart(osal_u16 ether_data_type,osal_u8 * ip_head)2639 osal_u32 hmac_m2u_sa_is_hwsmart(osal_u16 ether_data_type, osal_u8 *ip_head)
2640 {
2641 osal_u32 grp_addr;
2642 mac_ip_header_stru *ip_header;
2643
2644 if (ether_data_type != oal_host2net_short(ETHER_TYPE_IP)) {
2645 return OAL_FALSE;
2646 }
2647
2648 ip_header = (mac_ip_header_stru *)ip_head;
2649 grp_addr = oal_host2net_long(ip_header->daddr);
2650 if ((grp_addr == 0xeeeeeeee) ||
2651 (((grp_addr & 0xffff0000) >> 16) == 0xef7e) || /* 16:偏移取值 */
2652 (((grp_addr & 0xffff0000) >> 16) == 0xef76) || /* 16:偏移取值 */
2653 (((grp_addr & 0xffff0000) >> 16) == 0xef0a) || /* 16:偏移取值 */
2654 (((grp_addr & 0xffff0000) >> 16) == 0xef14) || /* 16:偏移取值 */
2655 (((grp_addr & 0xffff0000) >> 16) == 0xef1e) || /* 16:偏移取值 */
2656 (((grp_addr & 0xffff0000) >> 16) == 0xef28)) { /* 16:偏移取值 */
2657 return OAL_TRUE;
2658 } else {
2659 return OAL_FALSE;
2660 }
2661 }
2662
2663 /*****************************************************************************
2664 函 数 名 : hmac_m2u_sta_is_adaptive
2665 功能描述 : 判断是否处于配网模式状态
2666 输入参数 : hmac_vap vap结构体; mac_addr组播报文源mac地址
2667 输出参数 : OAL_FALSE OR OAL_TRUE
2668 *****************************************************************************/
hmac_m2u_sta_is_adaptive(hmac_vap_stru * hmac_vap,osal_u8 * mac_addr,mac_vlan_tag_stru * vlan_tag)2669 osal_u32 hmac_m2u_sta_is_adaptive(hmac_vap_stru *hmac_vap, osal_u8 *mac_addr,
2670 mac_vlan_tag_stru *vlan_tag)
2671 {
2672 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2673 hmac_m2u_adaptive_list_update_stru adaptive_list_entry;
2674 osal_u32 ret = OAL_FALSE;
2675
2676 memset_s(&adaptive_list_entry, OAL_SIZEOF(adaptive_list_entry), 0, OAL_SIZEOF(adaptive_list_entry));
2677 if (memcpy_s(&(adaptive_list_entry.new_member_mac), OAL_SIZEOF(adaptive_list_entry.new_member_mac),
2678 mac_addr, WLAN_MAC_ADDR_LEN) != EOK) {
2679 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_sta_is_adaptive::memcpy addr fail", hmac_vap->vap_id);
2680 }
2681 if (vlan_tag != OAL_PTR_NULL) {
2682 if (memcpy_s(&(adaptive_list_entry.outer_vlan_tag), OAL_SIZEOF(adaptive_list_entry.outer_vlan_tag),
2683 vlan_tag, OAL_SIZEOF(mac_vlan_tag_stru)) != EOK) {
2684 oam_warning_log1(0, OAM_SF_M2U, "vap[%d]hmac_m2u_sta_is_adaptive::memcpy vlan fail", hmac_vap->vap_id);
2685 }
2686 }
2687
2688 hash_adaptive = hmac_m2u_find_adaptive_list(hmac_vap, &adaptive_list_entry);
2689 if (hash_adaptive != OAL_PTR_NULL) {
2690 ret = hash_adaptive->m2u_adaptive;
2691 }
2692
2693 return ret;
2694 }
2695
2696 /*****************************************************************************
2697 函 数 名 : hmac_m2u_sa_is_hwsmart
2698 功能描述 : 组播报文是否为异频转发
2699 输入参数 : hmac_vap vap结构体; mac_addr组播报文源mac地址
2700 输出参数 : OAL_FALSE OR OAL_TRUE
2701 *****************************************************************************/
hmac_m2u_multicast_is_frequency(hmac_vap_stru * hmac_vap,osal_u8 * mac_addr)2702 osal_u32 hmac_m2u_multicast_is_frequency(hmac_vap_stru *hmac_vap, osal_u8 *mac_addr)
2703 {
2704 hmac_vap_stru *hmac_vap;
2705 hmac_device_stru *hmac_device;
2706 osal_u16 vap_idx;
2707 osal_u16 user_idx = 0;
2708 wlan_channel_band_enum_uint8 freq_band_now;
2709
2710 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
2711 oam_error_log0(0, OAM_SF_M2U, "hmac_m2u_multicast_is_frequency::hmac_vap is null}");
2712 return OAL_ERR_CODE_PTR_NULL;
2713 }
2714
2715 hmac_device = hmac_res_get_mac_dev_etc((osal_u32)hmac_vap->device_id);
2716 freq_band_now = hmac_vap->channel.band;
2717
2718 if (osal_unlikely(hmac_device == OAL_PTR_NULL)) {
2719 oam_error_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_multicast_is_frequency::hmac_device[%d] is NULL!}",
2720 hmac_vap->vap_id, hmac_vap->device_id);
2721 return OAL_ERR_CODE_PTR_NULL;
2722 }
2723
2724 for (vap_idx = 0; vap_idx < hmac_device->vap_num; vap_idx++) {
2725 hmac_vap = mac_res_get_hmac_vap(hmac_device->vap_id[vap_idx]);
2726 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
2727 continue;
2728 }
2729
2730 if (hmac_vap->vap_mode != WLAN_VAP_MODE_BSS_AP) {
2731 continue;
2732 }
2733
2734 if ((hmac_vap->channel.band == freq_band_now) &&
2735 (hmac_vap_find_user_by_macaddr_etc(hmac_vap, mac_addr, &user_idx) == OAL_SUCC)) {
2736 return OAL_FALSE;
2737 }
2738 }
2739 return OAL_TRUE;
2740 }
2741
2742 /*****************************************************************************
2743 函 数 名 : hmac_m2u_multicast_drop
2744 功能描述 : 发送方向不满足组播发送的进行DROP处理
2745 输入参数 : hmac_vap vap结构体; buf netbuf 结构体
2746 输出参数 : HMAC_TX_DROP_MCAST OR HMAC_TX_PASS
2747 *****************************************************************************/
hmac_m2u_multicast_drop(hmac_vap_stru * hmac_vap,oal_netbuf_stru * buf)2748 osal_u32 hmac_m2u_multicast_drop(hmac_vap_stru *hmac_vap, oal_netbuf_stru *buf)
2749 {
2750 mac_ether_header_stru *ether_hdr;
2751 osal_u16 ether_data_type;
2752 osal_u8 *ip_head;
2753 mac_vlan_tag_stru *vlan_tag;
2754 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2755
2756 /* 未打开组转单播开关,直接返回不处理 */
2757 if (OAL_FALSE == m2u->snoop_enable) {
2758 oam_warning_log2(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_multicast_drop::snoop is [%d] not enable}",
2759 hmac_vap->vap_id, m2u->snoop_enable);
2760 return HMAC_TX_PASS;
2761 }
2762 ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(buf);
2763 /* 带vlan tag 的情况 */
2764 if (ether_is_with_vlan_tag(ether_hdr->ether_type)) {
2765 // 偏移2个mac地址的长度,获取外层vlan tag
2766 vlan_tag = (mac_vlan_tag_stru *)(oal_netbuf_data(buf) + (ETHER_ADDR_LEN << 1));
2767 vlan_tag += 1;
2768 if (ether_is_with_vlan_tag(vlan_tag->tpid)) { // 双层tag的情况,内层tag不考虑
2769 ether_data_type = *((osal_u16 *)(vlan_tag + 1)); // 跳过内层tag后获取eth type
2770 ip_head = (osal_u8 *)(vlan_tag + 1) + 2; // 2:跳过 type 和内层指向ip头起始地址
2771 } else {
2772 ether_data_type = *((osal_u16 *)vlan_tag); // 跳过tag后获取eth type
2773 ip_head = (osal_u8 *)vlan_tag + 2; // 2:跳过 type 和tag指向ip头起始地址
2774 }
2775 vlan_tag -= 1; // 指向外层tag,作为参数传递到下层
2776 } else { /* 非vlan 的情况 */
2777 vlan_tag = OAL_PTR_NULL;
2778 ip_head = (osal_u8 *)(ether_hdr + 1);
2779 ether_data_type = ether_hdr->ether_type;
2780 }
2781
2782 /* 异频组播转发开关未打开 */
2783 if (m2u->frequency_enable == OAL_FALSE) {
2784 /* 异频组播转发关闭,不满足智能家居单品特征 */
2785 if ((hmac_m2u_sa_is_hwsmart(ether_data_type, ip_head) == OAL_FALSE) && (m2u->discard_mcast)) {
2786 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, 1, buf);
2787 return HMAC_TX_DROP_NOSMART;
2788 }
2789 } else { /* 异频组播转发开关打开 */
2790 /* 组播报文属于异频转发 */
2791 if (hmac_m2u_multicast_is_frequency(hmac_vap, ether_hdr->ether_shost)) {
2792 /* 组播报文来源STA不在配网模式 */
2793 if (((m2u->adaptive_enable == OAL_FALSE) ||
2794 (hmac_m2u_sta_is_adaptive(hmac_vap, ether_hdr->ether_shost, vlan_tag) == OAL_FALSE)) &&
2795 (m2u->discard_mcast)) {
2796 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, 1, buf);
2797 return HMAC_TX_DROP_NOADAP;
2798 }
2799 } else { /* 组播报文不属于异频转发 */
2800 /* 组播报文不属于异频转发,不满足智能家居单品特征 */
2801 if ((hmac_m2u_sa_is_hwsmart(ether_data_type, ip_head) == OAL_FALSE) && (m2u->discard_mcast)) {
2802 hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, 1, buf);
2803 return HMAC_TX_DROP_NOSMART;
2804 }
2805 }
2806 }
2807 return HMAC_TX_PASS;
2808 }
2809
2810 /*****************************************************************************
2811 函 数 名 : hmac_m2u_remove_old_sta
2812 功能描述 : 删除老化的配网STA
2813 输入参数 : p_arg 输入参数
2814 输出参数 : 无
2815 *****************************************************************************/
hmac_m2u_remove_old_sta(osal_void * p_arg)2816 osal_u32 hmac_m2u_remove_old_sta(osal_void *p_arg)
2817 {
2818 hmac_vap_stru *hmac_vap = (hmac_vap_stru *)p_arg;
2819 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2820 hmac_m2u_adaptive_hash_stru *hash_adaptive = OAL_PTR_NULL;
2821 struct osal_list_head *sta_list_entry;
2822 struct osal_list_head *sta_list_entry_temp;
2823 osal_u32 nowtime = (osal_u32)oal_time_get_stamp_ms();
2824 osal_u32 loop;
2825
2826 if (m2u == OAL_PTR_NULL) {
2827 return OAL_FAIL;
2828 }
2829
2830 /* 遍历配网STA组链表,找到地址匹配的配网STA */
2831 for (loop = 0; loop < HMAC_M2U_ADAPTIVE_STA_HASHSIZE; loop++) {
2832 osal_list_for_each_safe(sta_list_entry, sta_list_entry_temp,
2833 &(m2u->m2u_adaptive_hash[loop])) {
2834 hash_adaptive = osal_list_entry(sta_list_entry,
2835 hmac_m2u_adaptive_hash_stru, adaptive_entry);
2836 if ((hash_adaptive->m2u_adaptive == OAL_FALSE) ||
2837 ((hash_adaptive->m2u_adaptive == OAL_TRUE) &&
2838 (oal_time_get_runtime((hash_adaptive->timestamp), nowtime) >= (m2u->adaptive_timeout)))) {
2839 osal_list_del(&(hash_adaptive->adaptive_entry));
2840 oal_mem_free(hash_adaptive, OAL_TRUE);
2841 m2u->adaptive_sta_count--;
2842 }
2843 }
2844 }
2845 return OAL_SUCC;
2846 }
2847 #endif
2848
2849 /*****************************************************************************
2850 函 数 名 : hmac_m2u_time_fn
2851 功能描述 : 组播转单播的定时器,删除长时间沉默的成员
2852 输入参数 : p_arg 输入参数
2853 *****************************************************************************/
hmac_m2u_time_fn(osal_void * p_arg)2854 OAL_STATIC osal_u32 hmac_m2u_time_fn(osal_void *p_arg)
2855 {
2856 hmac_vap_stru *hmac_vap = (hmac_vap_stru *)p_arg;
2857 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
2858 hmac_m2u_snoop_list_stru *snp_list = &(m2u->m2u_snooplist);
2859 hmac_m2u_grp_list_entry_stru *grp_list;
2860 struct osal_list_head *grp_list_entry;
2861 struct osal_list_head *grp_list_entry_temp;
2862 osal_u32 ul_ret;
2863
2864 osal_u32 nowtime = (osal_u32)oal_time_get_stamp_ms();
2865
2866 osal_list_for_each_safe(grp_list_entry, grp_list_entry_temp, &(snp_list->grp_list)) {
2867 grp_list = (hmac_m2u_grp_list_entry_stru *)osal_list_entry(grp_list_entry,
2868 hmac_m2u_grp_list_entry_stru, grp_entry);
2869 ul_ret = hmac_m2u_remove_expired_member(grp_list, hmac_vap, nowtime); // 组成员
2870 if (ul_ret != OAL_SUCC) {
2871 return ul_ret;
2872 }
2873
2874 if ((osal_list_empty(&(grp_list->src_list))) == OAL_TRUE) {
2875 osal_list_del(&(grp_list->grp_entry));
2876 oal_mem_free(grp_list, OAL_TRUE);
2877 grp_list = OAL_PTR_NULL;
2878 snp_list->group_list_count--;
2879 }
2880 }
2881 return OAL_SUCC;
2882 }
2883
hmac_m2u_sepcial_group_init(hmac_m2u_snoop_list_stru * snp_list)2884 OAL_STATIC osal_void hmac_m2u_sepcial_group_init(hmac_m2u_snoop_list_stru *snp_list)
2885 {
2886 /* 特殊业务组播 IPV4 */
2887 snp_list->special_group_ipv4[0] = HMAC_M2U_SPECIAL_GROUP1; /* 224.0.0.1 */
2888 snp_list->special_group_ipv4[1] = HMAC_M2U_SPECIAL_GROUP2; /* 224.0.0.2 */
2889 snp_list->special_group_ipv4[2] = HMAC_M2U_RIPV2_GROUP; /* 224.0.0.9 */
2890 snp_list->special_group_ipv4[3] = HMAC_M2U_SPECIAL_GROUP3; /* 3:224.0.0.22 */
2891 snp_list->special_group_ipv4[4] = HMAC_M2U_UPNP_GROUP; /* 239.255.255.250 */
2892 /* 特殊业务组播 IPV6 */
2893 /* IPV6 ff02::1 */
2894 memset_s(snp_list->special_group_ipv6[0], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
2895 snp_list->special_group_ipv6[0][0] = 0xff;
2896 snp_list->special_group_ipv6[0][1] = 0x2;
2897 snp_list->special_group_ipv6[0][15] = 0x1; /* 15:ipv6第15位取地址 */
2898 /* IPV6 ff02::2 */
2899 memset_s(snp_list->special_group_ipv6[1], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
2900 snp_list->special_group_ipv6[1][0] = 0xff;
2901 snp_list->special_group_ipv6[1][1] = 0x2;
2902 snp_list->special_group_ipv6[1][15] = 0x2; /* 15:ipv6第15位取地址 */
2903 /* IPV6 ff02::16 */
2904 memset_s(snp_list->special_group_ipv6[2], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
2905 snp_list->special_group_ipv6[2][0] = 0xff; /* 2:特殊业务组播组 */
2906 snp_list->special_group_ipv6[2][1] = 0x2; /* 2:特殊业务组播组 */
2907 snp_list->special_group_ipv6[2][15] = 0x16; /* 2:特殊业务组播组,15:ipv6第15位取地址 */
2908 /* IPV6 ff02::1:2 */
2909 memset_s(snp_list->special_group_ipv6[3], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE); /* 3:特殊业务组播组 */
2910 snp_list->special_group_ipv6[3][0] = 0xff; /* 3:特殊业务组播组 */
2911 snp_list->special_group_ipv6[3][1] = 0x2; /* 3:特殊业务组播组 */
2912 snp_list->special_group_ipv6[3][13] = 0x1; /* 3:特殊业务组播组 */ /* 13:ipv6第13位取地址 */
2913 snp_list->special_group_ipv6[3][15] = 0x2; /* 3:特殊业务组播组 */ /* 15:ipv6第15位取地址 */
2914 /* IPV6 ff02::1:ff02:b */
2915 memset_s(snp_list->special_group_ipv6[4], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE); /* 4:特殊业务组播组 */
2916 snp_list->special_group_ipv6[4][0] = 0xff; /* 4:特殊业务组播组 */
2917 snp_list->special_group_ipv6[4][1] = 0x2; /* 4:特殊业务组播组 */
2918 snp_list->special_group_ipv6[4][11] = 0x1; /* 4:特殊业务组播组 */ /* 11:ipv6第12位取地址 */
2919 snp_list->special_group_ipv6[4][12] = 0xff; /* 4:特殊业务组播组,12:ipv6第12位取地址 */
2920 snp_list->special_group_ipv6[4][13] = 0x2; /* 4:特殊业务组播组,13:ipv6第13位取地址 */
2921 snp_list->special_group_ipv6[4][15] = 0xb; /* 4:特殊业务组播组,15:ipv6第15位取地址 */
2922 }
2923
hmac_m2u_deny_table_init(hmac_m2u_snoop_list_stru * snp_list)2924 OAL_STATIC osal_void hmac_m2u_deny_table_init(hmac_m2u_snoop_list_stru *snp_list)
2925 {
2926 /* 永久组播组(224.0.0.0~224.0.0.255)中的组播已加入到组播黑名单;不在此范围中的组播组,添加到deny_group */
2927 snp_list->deny_count_ipv4 = DEFAULT_IPV4_DENY_GROUP_COUNT; /* 默认额外添加1个组播为黑名单 */
2928 snp_list->deny_group[0] = HMAC_M2U_DENY_GROUP; /* 239.255.255.1 */
2929
2930 snp_list->deny_count_ipv6 = DEFAULT_IPV6_DENY_GROUP_COUNT;
2931 memset_s(snp_list->deny_group_ipv6[0], OAL_IPV6_ADDR_SIZE, 0, OAL_IPV6_ADDR_SIZE);
2932 snp_list->deny_group_ipv6[0][0] = 0xff; /* IPV6 LLMNR协议ff02::1:3 */
2933 snp_list->deny_group_ipv6[0][1] = 0x2;
2934 snp_list->deny_group_ipv6[0][13] = 0x1; /* 13:ipv6第13位取地址 */
2935 snp_list->deny_group_ipv6[0][15] = 0x3; /* 15:ipv6第15位取地址 */
2936 }
2937
2938 /*****************************************************************************
2939 函 数 名 : hmac_m2u_attach
2940 功能描述 : 组播转单播的初始化函数
2941 输入参数 : hmac_vap vap结构体
2942 输出参数 : 无
2943 *****************************************************************************/
hmac_m2u_attach(hmac_vap_stru * hmac_vap)2944 osal_void hmac_m2u_attach(hmac_vap_stru *hmac_vap)
2945 {
2946 hmac_m2u_stru *m2u = OSAL_NULL;
2947 hmac_m2u_snoop_list_stru *snp_list = OSAL_NULL;
2948
2949 if (hmac_vap->m2u != OAL_PTR_NULL) {
2950 return;
2951 }
2952
2953 m2u = (hmac_m2u_stru *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, OAL_SIZEOF(hmac_m2u_stru), OAL_TRUE);
2954 if (osal_unlikely(m2u == OAL_PTR_NULL)) {
2955 oam_error_log1(0, OAM_SF_M2U, "vap_id[%d] {hmac_m2u_attach::m2u is null!}",
2956 hmac_vap->vap_id);
2957 return;
2958 }
2959
2960 hmac_vap->m2u = m2u;
2961 snp_list = &(m2u->m2u_snooplist);
2962
2963 memset_s(m2u, OAL_SIZEOF(hmac_m2u_stru), 0, OAL_SIZEOF(hmac_m2u_stru));
2964 /* 启动定时器 */
2965 frw_create_timer_entry(&(m2u->snooplist_timer), hmac_m2u_time_fn, HMAC_DEF_M2U_TIMER, hmac_vap,
2966 OAL_TRUE);
2967
2968 m2u->snoop_enable = OAL_TRUE; /* 默认使能,组播转发时需要根据snoop表确认是否有用户再转发 */
2969 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2970 m2u->adaptive_enable = OAL_TRUE; /* 配网模式识别默认使能 */
2971 m2u->frequency_enable = OAL_TRUE; /* 异频组播转发默认使能 */
2972 #endif
2973
2974 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
2975 /* 启动配网老化定时器 1000:定时器1秒 */
2976 frw_create_timer_entry(&(m2u->adaptivelist_timer), hmac_m2u_remove_old_sta, 1000, hmac_vap,
2977 OAL_TRUE);
2978
2979 hmac_m2u_adaptive_list_init(hmac_vap);
2980
2981 m2u->threshold_time = HMAC_DEF_THRESHOLD_TIME;
2982 m2u->adaptive_timeout = HMAC_DEF_ADAPTIVE_TIMEOUT;
2983 m2u->adaptive_num = HMAC_DEF_NUM_OF_ADAPTIVE;
2984 #endif
2985
2986 hmac_m2u_sepcial_group_init(snp_list);
2987
2988 m2u->discard_mcast = OAL_TRUE;
2989 m2u->timeout = HMAC_DEF_M2U_TIMEOUT;
2990
2991 m2u->mcast_mode = HMAC_M2U_MCAST_TRANSLATE; /* 默认打开组播转单播开关 */
2992 hmac_m2u_deny_table_init(snp_list);
2993
2994 snp_list->total_sta_num = 0;
2995 snp_list->group_list_count = 0;
2996 hmac_m2u_snoop_list_init(hmac_vap);
2997 }
2998
2999 /*****************************************************************************
3000 函 数 名 : hmac_m2u_detach
3001 功能描述 : 组播转单播的detach
3002 输入参数 : hmac_vap vap结构体
3003 输出参数 : 无
3004 *****************************************************************************/
hmac_m2u_detach(hmac_vap_stru * hmac_vap)3005 osal_void hmac_m2u_detach(hmac_vap_stru *hmac_vap)
3006 {
3007 hmac_m2u_stru *m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
3008
3009 if (m2u != OAL_PTR_NULL) {
3010 hmac_m2u_clean_snp_list(hmac_vap);
3011 frw_destroy_timer_entry(&(m2u->snooplist_timer));
3012 #ifdef _PRE_WLAN_FEATURE_HERA_MCAST
3013 frw_destroy_timer_entry(&(m2u->adaptivelist_timer));
3014 hmac_m2u_clean_adaptive_list(hmac_vap);
3015 #endif
3016 oal_mem_free(m2u, OAL_TRUE);
3017 hmac_vap->m2u = OAL_PTR_NULL;
3018 }
3019 }
3020
hmac_m2u_feature_hook_register(osal_void)3021 OAL_STATIC osal_void hmac_m2u_feature_hook_register(osal_void)
3022 {
3023 /* 对外接口注册 */
3024 hmac_feature_hook_register(HMAC_FHOOK_M2U_SNOOP_INSPECTING, hmac_m2u_snoop_inspecting);
3025 hmac_feature_hook_register(HMAC_FHOOK_M2U_CLEANUP_SNOOPWDS_NODE, hmac_m2u_cleanup_snoopwds_node);
3026 hmac_feature_hook_register(HMAC_FHOOK_M2U_SNOOP_CONVERT, hmac_m2u_snoop_convert);
3027 hmac_feature_hook_register(HMAC_FHOOK_M2U_UNICAST_CONVERT_MULTICAST, hmac_m2u_unicast_convert_multicast);
3028 hmac_feature_hook_register(HMAC_FHOOK_M2U_ATTACH, hmac_m2u_attach);
3029 hmac_feature_hook_register(HMAC_FHOOK_M2U_DETACH, hmac_m2u_detach);
3030 return;
3031 }
3032
hmac_m2u_feature_hook_unregister(osal_void)3033 OAL_STATIC osal_void hmac_m2u_feature_hook_unregister(osal_void)
3034 {
3035 /* 对外接口去注册 */
3036 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_SNOOP_INSPECTING);
3037 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_CLEANUP_SNOOPWDS_NODE);
3038 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_SNOOP_CONVERT);
3039 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_UNICAST_CONVERT_MULTICAST);
3040 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_ATTACH);
3041 hmac_feature_hook_unregister(HMAC_FHOOK_M2U_DETACH);
3042 return;
3043 }
3044
3045 /*
3046 * 功能描述: 打开组播转单播snoop开关
3047 * 注意事项: 配置开关的同时,也需要配置模式
3048 */
hmac_m2u_snoop_on(hmac_vap_stru * hmac_vap,frw_msg * msg)3049 OAL_STATIC osal_s32 hmac_m2u_snoop_on(hmac_vap_stru *hmac_vap, frw_msg *msg)
3050 {
3051 mac_cfg_m2u_snoop_on_param_stru *m2u_snoop_on_param = OSAL_NULL;
3052 hmac_m2u_stru *m2u = OSAL_NULL;
3053
3054 if ((hmac_vap == OSAL_NULL) || (msg->data == OSAL_NULL)) {
3055 oam_error_log0(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:null ptr}");
3056 return OAL_ERR_CODE_PTR_NULL;
3057 }
3058
3059 hmac_m2u_attach(hmac_vap);
3060 m2u = (hmac_m2u_stru *)(hmac_vap->m2u);
3061 if (m2u == OSAL_NULL) {
3062 oam_error_log0(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:null m2u ptr}");
3063 return OAL_ERR_CODE_PTR_NULL;
3064 }
3065 m2u_snoop_on_param = (mac_cfg_m2u_snoop_on_param_stru *)msg->data;
3066
3067 if ((m2u_snoop_on_param->m2u_snoop_on != 0) && (m2u_snoop_on_param->m2u_snoop_on != 1)) {
3068 oam_error_log1(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:error param:%d", m2u_snoop_on_param->m2u_snoop_on);
3069 return OAL_FAIL;
3070 }
3071 m2u->snoop_enable = (m2u_snoop_on_param->m2u_snoop_on == 0) ? OAL_FALSE : OAL_TRUE;
3072
3073 if (m2u->snoop_enable == 1) {
3074 hmac_m2u_feature_hook_register();
3075 } else {
3076 hmac_m2u_feature_hook_unregister();
3077 }
3078
3079 if ((m2u_snoop_on_param->m2u_mcast_mode != 0) && (m2u_snoop_on_param->m2u_mcast_mode != 1) &&
3080 (m2u_snoop_on_param->m2u_mcast_mode != 2)) { /* 0表示维持maitain 1表示tunnel 2表示组播转单播转换 */
3081 oam_error_log1(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:error mode:%d", m2u_snoop_on_param->m2u_mcast_mode);
3082 return OAL_FAIL;
3083 }
3084 m2u->mcast_mode = m2u_snoop_on_param->m2u_mcast_mode;
3085 oam_warning_log0(0, OAM_SF_M2U, "CCPRIV m2u_snoop_enable OK");
3086 return OAL_SUCC;
3087 }
3088
hmac_show_m2u_snoop_table(hmac_vap_stru * hmac_vap,frw_msg * msg)3089 OAL_STATIC osal_s32 hmac_show_m2u_snoop_table(hmac_vap_stru *hmac_vap, frw_msg *msg)
3090 {
3091 unref_param(msg);
3092 if (hmac_vap == OSAL_NULL) {
3093 oam_error_log0(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:null ptr}");
3094 return OAL_ERR_CODE_PTR_NULL;
3095 }
3096
3097 /* show snoop 表 */
3098 hmac_m2u_print_all_snoop_list(hmac_vap, OSAL_NULL);
3099 return OAL_SUCC;
3100 }
3101
hmac_m2u_deny_table(hmac_vap_stru * hmac_vap,frw_msg * msg)3102 OAL_STATIC osal_s32 hmac_m2u_deny_table(hmac_vap_stru *hmac_vap, frw_msg *msg)
3103 {
3104 mac_cfg_m2u_deny_table_stru *cfg_deny_table = OSAL_NULL;
3105
3106 if ((hmac_vap == OSAL_NULL) || (msg->data == OSAL_NULL)) {
3107 oam_error_log0(0, OAM_SF_M2U, "{hmac_config_m2u_snoop_on:null ptr}");
3108 return OAL_ERR_CODE_PTR_NULL;
3109 }
3110
3111 cfg_deny_table = (mac_cfg_m2u_deny_table_stru *)msg->data;
3112 switch (cfg_deny_table->cfg_type) {
3113 case HMAC_H2U_DENY_TABLE_LIST:
3114 hmac_m2u_show_snoop_deny_table(hmac_vap);
3115 break;
3116 case HMAC_H2U_DENY_TABLE_CLEAR:
3117 hmac_m2u_clear_deny_table(hmac_vap);
3118 break;
3119 case HMAC_H2U_DENY_TABLE_ADD_IPV4:
3120 hmac_m2u_add_snoop_ipv4_deny_entry(hmac_vap, &cfg_deny_table->deny_group_ipv4_addr);
3121 break;
3122 case HMAC_H2U_DENY_TABLE_DEL_IPV4:
3123 hmac_m2u_del_ipv4_deny_entry(hmac_vap, &cfg_deny_table->deny_group_ipv4_addr);
3124 break;
3125 case HMAC_H2U_DENY_TABLE_ADD_IPV6:
3126 hmac_m2u_add_snoop_ipv6_deny_entry(hmac_vap, cfg_deny_table->deny_group_ipv6_addr);
3127 break;
3128 case HMAC_H2U_DENY_TABLE_DEL_IPV6:
3129 hmac_m2u_del_ipv6_deny_entry(hmac_vap, cfg_deny_table->deny_group_ipv6_addr);
3130 break;
3131 default:
3132 break;
3133 }
3134 return OAL_SUCC;
3135 }
3136
3137 /*
3138 * 功能描述: 组一个igmpv2 reprt报文
3139 * 注意事项: size表示报文长度, 包含以太网头部, 不包括FCS, 取值范围应该为60~1514
3140 */
hmac_m2u_create_igmp_packet(osal_u32 size,osal_u8 tid,osal_u8 * mac_ra,osal_u8 * mac_ta)3141 OAL_STATIC oal_netbuf_stru* hmac_m2u_create_igmp_packet(osal_u32 size, osal_u8 tid, osal_u8 *mac_ra, osal_u8 *mac_ta)
3142 {
3143 oal_netbuf_stru *net_buf = OSAL_NULL;
3144 mac_ether_header_stru *ether_header = OSAL_NULL;
3145 mac_ip_header_stru *ip_header = OSAL_NULL;
3146 mac_igmp_header_stru *igmp_hdr = OSAL_NULL;
3147 osal_u32 reserve = 256; /* 预留256个字节 */
3148
3149 net_buf = oal_netbuf_alloc(size + reserve, reserve, 4); /* 4字节对齐 */
3150 if (osal_unlikely(net_buf == OAL_PTR_NULL)) {
3151 return OAL_PTR_NULL;
3152 }
3153
3154 oal_netbuf_put(net_buf, size);
3155 oal_set_mac_addr(&net_buf->data[0], mac_ra);
3156 oal_set_mac_addr(&net_buf->data[6], mac_ta); /* 报文第6位填入ta mac地址 */
3157
3158 ether_header = (mac_ether_header_stru *)oal_netbuf_data(net_buf);
3159 ether_header->ether_type = oal_host2net_short(ETHER_TYPE_IP);
3160 ip_header = (mac_ip_header_stru *)(ether_header + 1); /* 偏移以太网头,取ip头 */
3161 ip_header->version_ihl = 0x45; /* 0x45 ip协议号和长度 */
3162 ip_header->tos = (osal_u8)(tid << WLAN_IP_PRI_SHIFT);
3163 ip_header->protocol = IPPROTO_IGMP;
3164 ip_header->tot_len = oal_byteorder_net_to_host_uint16(0x0020); /* 0x0020报文长度 */
3165 ip_header->frag_off = 0x0000;
3166 ip_header->ttl = 0x01;
3167
3168 /* 指向igmp头指针 */
3169 igmp_hdr = (mac_igmp_header_stru *)(ip_header + 1);
3170 igmp_hdr->type = MAC_IGMPV2_REPORT_TYPE;
3171 igmp_hdr->code = 0x64; /* 0x64代表max resp time,协议建议值 */
3172 igmp_hdr->csum = oal_byteorder_net_to_host_uint16(0xfafb); /* igmp校验码是0xfafb */
3173 igmp_hdr->group = oal_byteorder_host_to_net_uint32(0xef000003); /* 固定组为0xef000003,即239.0.0.3进行测试 */
3174
3175 net_buf->next = OAL_PTR_NULL;
3176 net_buf->prev = OAL_PTR_NULL;
3177
3178 memset_s(oal_netbuf_cb(net_buf), OAL_NETBUF_CB_SIZE(), 0, OAL_NETBUF_CB_SIZE());
3179 return net_buf;
3180 }
3181
3182 /*
3183 * 功能描述: 发送一个IGMP报文
3184 * 注意事项: size表示报文长度, 包含以太网头部, 不包括FCS, 取值范围应该为60~1514
3185 */
hmac_m2u_igmp_packet_xmit(hmac_vap_stru * hmac_vap,frw_msg * msg)3186 OAL_STATIC osal_s32 hmac_m2u_igmp_packet_xmit(hmac_vap_stru *hmac_vap, frw_msg *msg)
3187 {
3188 mac_cfg_mpdu_ampdu_tx_param_stru *ampdu_tx_on_param = OSAL_NULL;
3189 osal_u8 skb_num;
3190 osal_u8 skb_idx;
3191 osal_u8 tid;
3192 osal_u16 packet_len;
3193 oal_net_device_stru *dev = OSAL_NULL;
3194 oal_netbuf_stru *netbuf[32] = {OAL_PTR_NULL}; /* 最多32个报文 */
3195
3196 ampdu_tx_on_param = (mac_cfg_mpdu_ampdu_tx_param_stru *)msg->data;
3197 skb_num = ampdu_tx_on_param->packet_num;
3198 tid = ampdu_tx_on_param->tid;
3199 packet_len = ampdu_tx_on_param->packet_len;
3200
3201 dev = hmac_vap_get_net_device_etc(hmac_vap->vap_id);
3202 if (dev == OAL_PTR_NULL) {
3203 return OAL_SUCC;
3204 }
3205
3206 if (skb_num <= 32) { /* 最多32个报文 */
3207 for (skb_idx = 0; skb_idx < skb_num; skb_idx++) {
3208 netbuf[skb_idx] = hmac_m2u_create_igmp_packet(packet_len, tid,
3209 ampdu_tx_on_param->ra_mac,
3210 hmac_vap->mib_info->wlan_mib_sta_config.dot11_station_id);
3211 frw_host_post_data(FRW_NETBUF_W2H_DATA_FRAME, hmac_vap->vap_id, netbuf[skb_idx]);
3212 }
3213 }
3214 return OAL_SUCC;
3215 }
3216
hmac_m2u_init(osal_void)3217 osal_u32 hmac_m2u_init(osal_void)
3218 {
3219 /* 消息注册 */
3220 frw_msg_hook_register(WLAN_MSG_W2H_CFG_M2U_SNOOP_ON, hmac_m2u_snoop_on);
3221 frw_msg_hook_register(WLAN_MSG_W2H_CFG_M2U_DENY_TABLE, hmac_m2u_deny_table);
3222 frw_msg_hook_register(WLAN_MSG_W2H_CFG_SHOW_M2U_SNOOP_TABLE, hmac_show_m2u_snoop_table);
3223 frw_msg_hook_register(WLAN_MSG_W2H_CFG_IGMP_PACKET_XMIT, hmac_m2u_igmp_packet_xmit);
3224
3225 return OAL_SUCC;
3226 }
3227
hmac_m2u_deinit(osal_void)3228 osal_void hmac_m2u_deinit(osal_void)
3229 {
3230 /* 消息去注册 */
3231 frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_M2U_SNOOP_ON);
3232 frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_M2U_DENY_TABLE);
3233 frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_SHOW_M2U_SNOOP_TABLE);
3234 frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_IGMP_PACKET_XMIT);
3235
3236 return;
3237 }
3238
3239 oal_module_symbol(hmac_m2u_snoop_inspecting);
3240 oal_module_symbol(hmac_m2u_attach);
3241 oal_module_symbol(hmac_m2u_snoop_convert);
3242 oal_module_symbol(hmac_m2u_detach);
3243 oal_module_symbol(hmac_m2u_clear_deny_table);
3244 oal_module_symbol(hmac_m2u_print_all_snoop_list);
3245 oal_module_symbol(hmac_m2u_show_snoop_deny_table);
3246 oal_module_symbol(hmac_m2u_add_snoop_ipv4_deny_entry);
3247 oal_module_symbol(hmac_m2u_add_snoop_ipv6_deny_entry);
3248 oal_module_symbol(hmac_m2u_del_ipv4_deny_entry);
3249 oal_module_symbol(hmac_m2u_del_ipv6_deny_entry);
3250 oal_module_symbol(hmac_m2u_cleanup_snoopwds_node);
3251 oal_module_symbol(hmac_m2u_unicast_convert_multicast);
3252
3253 #ifdef __cplusplus
3254 #if __cplusplus
3255 }
3256 #endif
3257 #endif
3258