1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "flow_control.h"
10
11 #include "flow_control_task.h"
12 #include "securec.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #include "net_device.h"
16 #include "net_device_adapter.h"
17
18 #define HDF_LOG_TAG "WiFiFlowControl"
19 #define ETHER_TYPE_PROCESS_COUNT 8
20 #define TOS_TO_ID_COUNT 6
21 #define PROTOCOL_STANDARD_SHIFT_COUNT 2
22 static FlowControlQueueID g_tosToIdHash[TOS_TO_ID_COUNT] = {
23 BE_QUEUE_ID, BK_QUEUE_ID, BK_QUEUE_ID, BE_QUEUE_ID, VI_QUEUE_ID, VI_QUEUE_ID
24 };
25
26 static FlowControlQueueID IpProcessFunc(const void *buff, uint32_t len);
27 static struct EtherProcessMap g_etherTypeProMap[ETHER_TYPE_PROCESS_COUNT] = {
28 {ETHER_TYPE_IP, IpProcessFunc},
29 {ETHER_TYPE_IPV6, NULL},
30 {ETHER_TYPE_PAE, NULL},
31 {ETHER_TYPE_TDLS, NULL},
32 {ETHER_TYPE_PPP_DISC, NULL},
33 {ETHER_TYPE_PPP_SES, NULL},
34 {ETHER_TYPE_WAI, NULL},
35 {ETHER_TYPE_VLAN, NULL},
36 };
37
TosToFcQueueId(uint8_t priority)38 static FlowControlQueueID TosToFcQueueId(uint8_t priority)
39 {
40 if (priority >= TOS_TO_ID_COUNT) {
41 return VO_QUEUE_ID;
42 }
43 return g_tosToIdHash[priority];
44 }
45
IsDhcpPort(struct UdpHeader * udpHdr,uint32_t len)46 static bool IsDhcpPort(struct UdpHeader *udpHdr, uint32_t len)
47 {
48 if (udpHdr == NULL) {
49 HDF_LOGE("%s udpHdr: = null!", __func__);
50 return false;
51 }
52 if (len < sizeof(struct UdpHeader)) {
53 HDF_LOGE("%s len not right!", __func__);
54 return false;
55 }
56 if ((ntohs(udpHdr->dest) == DHCP_UDP_SRC_PORT) || (ntohs(udpHdr->dest) == DHCP_UDP_DES_PORT)) {
57 return true;
58 }
59 return false;
60 }
61
62 /* TcpKeyFrame:ACK/SYN */
IsTcpKeyFrame(struct IpHeader * ipHeader,uint32_t len)63 static bool IsTcpKeyFrame(struct IpHeader *ipHeader, uint32_t len)
64 {
65 struct TcpHeader *tcpHdr = NULL;
66 uint32_t ipPktLen;
67 uint32_t tcpHdrLen;
68 uint8_t ipHdrLen;
69 uint8_t *ip = NULL;
70 if (ipHeader == NULL) {
71 HDF_LOGE("IsTcpAck Fail ipHeader = null");
72 return false;
73 }
74 if (len < sizeof(struct IpHeader)) {
75 HDF_LOGE("%s len not right!", __func__);
76 return false;
77 }
78 if ((len - sizeof(struct IpHeader)) < sizeof(struct TcpHeader)) {
79 HDF_LOGE("%s tcp hdr len not right!", __func__);
80 return false;
81 }
82
83 tcpHdr = (struct TcpHeader *)(ipHeader + 1);
84 ip = (uint8_t *)(ipHeader);
85 ipPktLen = ntohs(ipHeader->totLen);
86 ipHdrLen = ((*ip) & 0x0F) << PROTOCOL_STANDARD_SHIFT_COUNT;
87 tcpHdrLen = (tcpHdr->offset & 0xF0) << PROTOCOL_STANDARD_SHIFT_COUNT;
88 if (tcpHdrLen + ipHdrLen == ipPktLen) {
89 return true;
90 }
91 return false;
92 }
93
IpProcessFunc(const void * buff,uint32_t len)94 static FlowControlQueueID IpProcessFunc(const void *buff, uint32_t len)
95 {
96 struct IpHeader *ipHeader = NULL;
97 struct UdpHeader *udpHdr = NULL;
98 FlowControlQueueID id = NORMAL_QUEUE_ID;
99 if (buff == NULL) {
100 HDF_LOGE("%s fail: buff = null!", __func__);
101 return QUEUE_ID_COUNT;
102 }
103 if (len < sizeof(struct IpHeader)) {
104 HDF_LOGE("%s fail: IpHeader len not right!", __func__);
105 return QUEUE_ID_COUNT;
106 }
107 ipHeader = (struct IpHeader *)buff;
108 if (ipHeader->protocol == UDP_PROTOCOL) {
109 /* from IP TOS find priority */
110 /*
111 * ----------------------------------------------------------------------
112 * tos define
113 * ----------------------------------------------------------------------
114 * | bit7~bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
115 * | priority | Delay | Throughput | reliability | Transmission cost | reserve |
116 * ----------------------------------------------------------------------
117 */
118 id = TosToFcQueueId(ipHeader->tos >> IP_PRI_SHIFT);
119 if ((len - sizeof(struct IpHeader)) < sizeof(struct UdpHeader)) {
120 HDF_LOGE("%s fail: UdpHeader len not right!", __func__);
121 return QUEUE_ID_COUNT;
122 }
123 udpHdr = (struct UdpHeader *)(ipHeader + 1);
124 if (((ntohs(ipHeader->fragInfo) & 0x1FFF) == 0) && IsDhcpPort(udpHdr, len - sizeof(struct IpHeader))) {
125 id = VIP_QUEUE_ID;
126 }
127 } else if (ipHeader->protocol == TCP_PROTOCOL) {
128 if (IsTcpKeyFrame(ipHeader, len)) {
129 id = TCP_ACK_QUEUE_ID;
130 } else {
131 id = TCP_DATA_QUEUE_ID;
132 }
133 }
134 return id;
135 }
136
FlowControlQueueInit(struct FlowControlModule * fcm)137 static void FlowControlQueueInit(struct FlowControlModule *fcm)
138 {
139 int32_t i, j;
140 if (fcm == NULL) {
141 HDF_LOGE("%s fail: fcm = null!", __func__);
142 return;
143 }
144 for (i = 0; i < FLOW_DIR_COUNT; i++) {
145 for (j = 0; j < QUEUE_ID_COUNT; j++) {
146 NetBufQueueInit(&fcm->fcmQueue[i].queues[j].dataQueue);
147 OsalSpinInit(&fcm->fcmQueue[i].queues[j].lock);
148 }
149 }
150 }
151
FlowControlQueueDeinit(struct FlowControlModule * fcm)152 static void FlowControlQueueDeinit(struct FlowControlModule *fcm)
153 {
154 int32_t i, j;
155 if (fcm == NULL) {
156 HDF_LOGE("%s fcm already free!", __func__);
157 return;
158 }
159
160 for (i = 0; i < FLOW_DIR_COUNT; i++) {
161 for (j = 0; j < QUEUE_ID_COUNT; j++) {
162 NetBufQueueClear(&fcm->fcmQueue[i].queues[j].dataQueue);
163 OsalSpinDestroy(&fcm->fcmQueue[i].queues[j].lock);
164 }
165 }
166 return;
167 }
168
SchedTransfer(struct FlowControlModule * fcm,FlowDir dir)169 static int32_t SchedTransfer(struct FlowControlModule *fcm, FlowDir dir)
170 {
171 if (fcm == NULL || dir >= FLOW_DIR_COUNT) {
172 HDF_LOGE("%s : fcm = null dir=%d!", __func__, dir);
173 return HDF_ERR_INVALID_PARAM;
174 }
175 OsalSemPost(&fcm->sem[dir]);
176 return HDF_SUCCESS;
177 }
178
RegisterFlowControlOp(struct FlowControlModule * fcm,struct FlowControlOp * op)179 static int32_t RegisterFlowControlOp(struct FlowControlModule *fcm, struct FlowControlOp *op)
180 {
181 if ((fcm == NULL) || (op == NULL)) {
182 HDF_LOGE("%s fail : fcm = null or op = null!", __func__);
183 return HDF_ERR_INVALID_PARAM;
184 }
185 fcm->op = op;
186 return HDF_SUCCESS;
187 }
188
IsValidSentToFCMPra(const struct FlowControlModule * fcm,uint32_t id,uint32_t dir)189 static bool IsValidSentToFCMPra(const struct FlowControlModule *fcm, uint32_t id, uint32_t dir)
190 {
191 if (fcm == NULL) {
192 HDF_LOGE("%s fail : fcm = null or buff = null!", __func__);
193 return false;
194 }
195 if (id >= QUEUE_ID_COUNT || dir >= FLOW_DIR_COUNT) {
196 HDF_LOGE("%s fail : id or dir not right!", __func__);
197 return false;
198 }
199 return true;
200 }
201
SetQueueThreshold(struct FlowControlModule * fcm,uint32_t queueThreshold,uint32_t id,uint32_t dir)202 static int32_t SetQueueThreshold(struct FlowControlModule *fcm, uint32_t queueThreshold, uint32_t id, uint32_t dir)
203 {
204 struct FlowControlQueue *fcmQueue = NULL;
205 if (!IsValidSentToFCMPra(fcm, id, dir)) {
206 HDF_LOGE("%s fail IsValidSentToFCMPra FALSE!", __func__);
207 return HDF_ERR_INVALID_PARAM;
208 }
209 fcmQueue = &fcm->fcmQueue[dir].queues[id];
210 fcmQueue->queueThreshold = queueThreshold;
211 return HDF_SUCCESS;
212 }
213
FcmQueuePreProcess(struct FlowControlQueue * fcmQueue)214 static void FcmQueuePreProcess(struct FlowControlQueue *fcmQueue)
215 {
216 NetBufQueue *dataQ = &fcmQueue->dataQueue;
217 NetBuf *oldBuff = NULL;
218 uint32_t threshold = fcmQueue->queueThreshold;
219 uint32_t qLen = NetBufQueueSize(dataQ);
220 if (threshold > 0 && threshold < qLen) {
221 HDF_LOGE("%s abandon netbuff!", __func__);
222 oldBuff = NetBufQueueDequeue(dataQ);
223 if (oldBuff != NULL) {
224 NetBufFree(oldBuff);
225 }
226 }
227 return;
228 }
229
SendBuffToFCM(struct FlowControlModule * fcm,NetBuf * buff,uint32_t id,uint32_t dir)230 static int32_t SendBuffToFCM(struct FlowControlModule *fcm, NetBuf *buff, uint32_t id, uint32_t dir)
231 {
232 struct FlowControlQueue *fcmQueue = NULL;
233 NetBufQueue *dataQ = NULL;
234 if ((buff == NULL) || (NetBufGetDataLen(buff) == 0)) {
235 HDF_LOGE("%s fail : buff=null or len=0!", __func__);
236 return HDF_ERR_INVALID_PARAM;
237 }
238 if (!IsValidSentToFCMPra(fcm, id, dir)) {
239 HDF_LOGE("%s fail : IsValidSentToFCMPra FALSE!", __func__);
240 return HDF_ERR_INVALID_PARAM;
241 }
242
243 fcmQueue = &fcm->fcmQueue[dir].queues[id];
244 dataQ = &fcmQueue->dataQueue;
245 FcmQueuePreProcess(fcmQueue);
246 if (NetBufQueueIsEmpty(dataQ)) {
247 fcm->fcmQueue[dir].queues[id].pktCount = 0;
248 }
249 NetBufQueueEnqueue(dataQ, buff);
250 fcm->fcmQueue[dir].queues[id].pktCount++;
251 return HDF_SUCCESS;
252 }
253
GetQueueIdByEtherBuff(const NetBuf * buff)254 static FlowControlQueueID GetQueueIdByEtherBuff(const NetBuf *buff)
255 {
256 uint32_t len;
257 struct EtherHeader *header = NULL;
258 int i;
259 uint16_t etherType = 0;
260 if (buff == NULL) {
261 HDF_LOGE("%s fail : buff = null!", __func__);
262 return QUEUE_ID_COUNT;
263 }
264 len = NetBufGetDataLen(buff);
265 if (len < sizeof(struct EtherHeader)) {
266 HDF_LOGE("%s fail : buff->data_len not right!", __func__);
267 return QUEUE_ID_COUNT;
268 }
269 header = (struct EtherHeader *)NetBufGetAddress(buff, E_DATA_BUF);
270 etherType = ntohs(header->etherType);
271
272 /* if processFun = null return VIP_QUEUE_ID */
273 for (i = 0; i < ETHER_TYPE_PROCESS_COUNT; i++) {
274 if (g_etherTypeProMap[i].etherType == etherType) {
275 if (g_etherTypeProMap[i].processFun != NULL) {
276 return g_etherTypeProMap[i].processFun((void *)(header + 1), len - sizeof(struct EtherHeader));
277 }
278 return VIP_QUEUE_ID;
279 }
280 }
281 return NORMAL_QUEUE_ID;
282 }
283
284 static struct FlowControlInterface g_fcInterface = {
285 .setQueueThreshold = SetQueueThreshold,
286 .getQueueIdByEtherBuff = GetQueueIdByEtherBuff,
287 .sendBuffToFCM = SendBuffToFCM,
288 .schedFCM = SchedTransfer,
289 .registerFlowControlOp = RegisterFlowControlOp,
290 };
291
292 static struct FlowControlModule *g_fcm = NULL;
293
SendFlowControlQueue(struct FlowControlModule * fcm,uint32_t id,uint32_t dir)294 int32_t SendFlowControlQueue(struct FlowControlModule *fcm, uint32_t id, uint32_t dir)
295 {
296 NetBufQueue *q = NULL;
297 int32_t fwPriorityId = 0;
298 int32_t rxPriorityId = 0;
299 if (!IsValidSentToFCMPra(fcm, id, dir)) {
300 HDF_LOGE("%s fail : IsValidSentToFCMPra FALSE!", __func__);
301 return HDF_ERR_INVALID_PARAM;
302 }
303 q = &fcm->fcmQueue[dir].queues[id].dataQueue;
304 if (NetBufQueueIsEmpty(q)) {
305 return HDF_SUCCESS;
306 }
307 if (dir == FLOW_TX) {
308 if (fcm->op != NULL && fcm->op->getTxPriorityId != NULL) {
309 fwPriorityId = fcm->op->getTxPriorityId(id);
310 }
311 if (fcm->op != NULL && fcm->op->txDataPacket != NULL) {
312 fcm->op->txDataPacket(q, fcm->fcmPriv, fwPriorityId);
313 } else {
314 HDF_LOGE("%s fail : fcm->op->txDataPacket = null!", __func__);
315 return HDF_ERR_INVALID_PARAM;
316 }
317 }
318
319 if (dir == FLOW_RX) {
320 if (fcm->op != NULL && fcm->op->getRxPriorityId != NULL) {
321 rxPriorityId = fcm->op->getRxPriorityId(id);
322 }
323 if (fcm->op != NULL && fcm->op->rxDataPacket != NULL) {
324 fcm->op->rxDataPacket(q, fcm->fcmPriv, rxPriorityId);
325 } else {
326 HDF_LOGE("%s fail : fcm->op->txDataPacket = null!", __func__);
327 return HDF_ERR_INVALID_PARAM;
328 }
329 }
330 return HDF_SUCCESS;
331 }
332
InitFlowControl(void * fcmPriv)333 struct FlowControlModule *InitFlowControl(void *fcmPriv)
334 {
335 struct FlowControlModule *fcm = NULL;
336 int i;
337 if (g_fcm != NULL) {
338 HDF_LOGE("%s already init", __func__);
339 return g_fcm;
340 }
341 fcm = (struct FlowControlModule *)OsalMemCalloc(sizeof(struct FlowControlModule));
342 if (fcm == NULL) {
343 HDF_LOGE("%s fail: malloc fail!", __func__);
344 return NULL;
345 }
346 (void)memset_s(fcm, sizeof(struct FlowControlModule), 0, sizeof(struct FlowControlModule));
347
348 /* init queue */
349 FlowControlQueueInit(fcm);
350
351 /* init wait */
352 for (i = 0; i < FLOW_DIR_COUNT; i++) {
353 if (OsalSemInit(&fcm->sem[i], 0) != HDF_SUCCESS) {
354 HDF_LOGE("%s init osalsem fail!", __func__);
355 if (i == FLOW_RX) {
356 OsalSemDestroy(&fcm->sem[FLOW_TX]);
357 }
358 OsalMemFree(fcm);
359 return NULL;
360 }
361 }
362
363 /* init task */
364 if (CreateFlowControlTask(fcm) != HDF_SUCCESS) {
365 HDF_LOGE("%s fail: CreateFlowControlTask fail!", __func__);
366 for (i = 0; i < FLOW_DIR_COUNT; i++) {
367 (void)OsalSemDestroy(&fcm->sem[i]);
368 }
369 OsalMemFree(fcm);
370 return NULL;
371 }
372
373 /* register interface */
374 fcm->interface = &g_fcInterface;
375 fcm->fcmPriv = fcmPriv;
376 g_fcm = fcm;
377 return fcm;
378 }
379
DeInitFlowControl(struct FlowControlModule * fcm)380 void DeInitFlowControl(struct FlowControlModule *fcm)
381 {
382 int i;
383 if (fcm == NULL) {
384 HDF_LOGE("%s fail : fcm already been free.", __func__);
385 return;
386 }
387
388 /* 1:Destroy task. 2:Destroy osalwait. 3:free NetBuff. */
389 DestroyFlowControlTask(fcm);
390 for (i = 0; i < FLOW_DIR_COUNT; i++) {
391 OsalSemDestroy(&fcm->sem[i]);
392 }
393 FlowControlQueueDeinit(fcm);
394 OsalMemFree(fcm);
395 g_fcm = NULL;
396 return;
397 }
398
GetFlowControlModule()399 struct FlowControlModule *GetFlowControlModule()
400 {
401 return g_fcm;
402 }
403