• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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