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