620 lines
18 KiB
C
Raw Normal View History

2025-04-10 17:31:33 +08:00
#include "lwip/opt.h"
#include "lwip/netif.h"
#include "lwip/dns.h"
#include "lwip/tcpip.h"
#include "lwip/ip.h"
#include "lwip/priv/tcpip_priv.h"
#include "lwip/priv/api_msg.h"
#include "wificliif.h"
#include "psifapi.h"
#ifdef FEATURE_WIFI_SWITCH_ENABLE
extern UlPduBlock* NetifUlGetOnePkg(UlPduBlock *pUlHdr,
UlPduBlock **ppOnePkgHead,
UlPduBlock **ppOnePkgTail,
UINT16 *pPkgLen);
extern void* PsDlPkgAlloc(UINT32 wantedSize);
extern void PsifInitPsDlPkgPbuf(DlPduBlock *pDlPduBlk);
extern UINT16 NetifCopyDataFromUlPdu(UINT8 *payload, UlPduBlock *pUlPdu);
extern void NetifDumpDlPduPacket(DlPduBlock *dlData, UINT8 type);
WifiCliUlPkgPendingList gWifiCliUlpkgPendingList = {0};
wifiCliOutputFunc wifiOutPutCustFunc = NULL;
void UlPduAddList(UlPduBlock **ppHdr, UlPduBlock **ppTailer, UlPduBlock *pNewHdr, UlPduBlock *pNewTailer)
{
if ((*ppHdr) == PNULL)
{
OsaCheck((*ppTailer) == PNULL && (pNewHdr) != PNULL && ((pNewTailer)->pNext) == PNULL, (*ppTailer), ((pNewTailer)->pNext), 0x12345678);
(*ppHdr) = (pNewHdr);
(*ppTailer) = (pNewTailer);
}
else
{
OsaCheck((*ppTailer) != PNULL && (pNewHdr) != PNULL && ((pNewTailer)->pNext) == PNULL, (*ppTailer), ((pNewTailer)->pNext), 0x87654321);
(*ppTailer)->pNext = (pNewHdr);
(*ppTailer) = (pNewTailer);
}
}
/******************************************************************************
* wifi_cli_ulPkg_ListGet
* Description: Get all UL PDU list from "gWifiCliUlpkgPendingList"
* input:
* ppHead //in & out
* output:
* Comment: this called in LWIP task
******************************************************************************/
static void wifi_cli_ulPkg_ListGet(UlPduBlock **ppHead)
{
WifiCliUlPkgPendingList *pPendingList = PNULL;
UINT32 mask = 0;
OsaCheck(ppHead != PNULL, ppHead, 0, 0);
*ppHead = PNULL;
mask = SaveAndSetIRQMask();
pPendingList = &gWifiCliUlpkgPendingList;
if (pPendingList != PNULL)
{
if (pPendingList->pHead != PNULL)
{
OsaCheck(pPendingList->pTail != PNULL && pPendingList->pTail->pNext == PNULL,
pPendingList->pTail, 0, 0);
*ppHead = pPendingList->pHead;
}
pPendingList->pHead = pPendingList->pTail = PNULL;
pPendingList->pkgNum = 0;
}
RestoreIRQMask(mask);
return;
}
/******************************************************************************
* wifi_cli_ul_output
* Description: Just pass UL raw IP pkg to wifi client
* input: struct netif *netif,
* struct pbuf *p,
* output:
* Comment:
* Current only support pass ether PKG one by one
******************************************************************************/
err_t wifi_cli_ul_output(struct netif *netif, struct pbuf *p)
{
DlPduBlock *pDlPdu = PNULL;
UINT16 totalLen = 0;
UINT8 *pBuf = PNULL;
//check PPP link state
if(!netif_is_link_up(netif))
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_cli_ul_output_if_down, P_WARNING, 0,
"wifi cli if is not link up");
return ERR_IF;
}
if (p->tot_len > netif->mtu)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_cli_ul_output_1, P_WARNING, 3,
"UL pkg Len: %d > MTU: %d, ignore this pkg", p->tot_len, netif->mtu);
return ERR_ARG;
}
totalLen = LLLNK_DLPDU_CONSUMED_SIZE(LWIP_PBUF_STRUCT_LEN + sizeof(DlPduBlock) + p->tot_len);
pBuf = (UINT8 *)PsDlPkgAlloc(totalLen);
if (pBuf == PNULL)
{
return ERR_MEM;
}
pDlPdu = (DlPduBlock *)(pBuf + LWIP_PBUF_STRUCT_LEN);
memset(pDlPdu, 0x00, sizeof(DlPduBlock));
DL_PDU_BLOCK_SET_MAGIC_WORD(pDlPdu);
pDlPdu->length = p->tot_len;
pDlPdu->pPdu = pBuf + LWIP_PBUF_STRUCT_LEN + sizeof(DlPduBlock) + LLLNK_DLPDU_RSVD_HDR_SIZE;
pDlPdu->dlMemType = DL_PS_PKG_MEM;
pDlPdu->pbufBefore = TRUE;
pDlPdu->bNetHdrRsvd = FALSE;
/* init pbuf struct */
PsifInitPsDlPkgPbuf(pDlPdu);
/* copy this ip pkg */
pbuf_copy_partial(p, (void *)pDlPdu->pPdu, p->tot_len, 0);
//dump pkg for debug
NetifDumpDlPduPacket(pDlPdu, LWIP_NETIF_TYPE_WAN_INTERNET);
//need add send the dlpdu to wifi client
// and wifi client process this dlpdu, must call PsifFreeDlIpPkgBlockList(pDlPdu);
if(wifiOutPutCustFunc)
{
wifiOutPutCustFunc(0, pDlPdu);
}
else
{
OsaFreeDlPduBlockList(&pDlPdu);
}
return ERR_OK;
}
/******************************************************************************
* wifi_cli_ip4_output
* Description: Just pass UL raw IPv4 pkg to wifi client
* input: struct netif *netif,
* struct pbuf *p,
* output:
* Comment:
* Current only support pass ether PKG one by one
******************************************************************************/
static err_t wifi_cli_ip4_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr)
{
// todo:you can add some check function
return wifi_cli_ul_output(netif, p);
}
/******************************************************************************
* wifi_cli_ip6_output
* Description: Just pass UL raw IPv6 pkg to wifi client
* input: struct netif *netif,
* struct pbuf *p,
* output:
* Comment:
* Current only support pass ether PKG one by one
******************************************************************************/
static err_t wifi_cli_ip6_output(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
{
// todo:you can add some check function
return wifi_cli_ul_output(netif, p);
}
/******************************************************************************
* wifi_cli_netif_init
* Description: wifi client netif init
* input: struct netif *netif,
* output:
* Comment:
*
******************************************************************************/
err_t wifi_cli_netif_init(struct netif *netif)
{
if(!netif)
return ERR_ARG;
//init netif name
netif->name[0] = WIFI_CLI_NETIF_PREFIX_NAME;
netif->name[1] = WIFI_CLI_NETIF_NAME;
//init ipv4 & ipv6 output function
netif->output = wifi_cli_ip4_output;
netif->primary_ipv4_cid = LWIP_PS_INVALID_CID;
#if LWIP_IPV6
netif->output_ip6 = wifi_cli_ip6_output;
netif->primary_ipv6_cid = LWIP_PS_INVALID_CID;
#endif /* LWIP_IPV6 */
netif->linkoutput = wifi_cli_ul_output;
#if LWIP_IGMP
netif->flags &= NETIF_FLAG_IGMP;
#endif
#if LWIP_IPV6_MLD
netif->flags &= NETIF_FLAG_MLD6;
#endif
return ERR_OK;
}
/******************************************************************************
* wifi_client_wan_linkup_callback
* Description: wifi client wan linkup call back
* input: NmWifiCliConfiguration *conf
* output:
* Comment:
*
******************************************************************************/
err_t wifi_client_wan_linkup_callback(NmWifiCliConfiguration *conf)
{
struct netif *wifi_cli_netif = NULL;
ip4_addr_t wifi_netif_netmask;
u8_t i;
if(conf == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkup_callback_1, P_WARNING, 0, "invalid argument");
}
//check whether wifi wan has linkup
wifi_cli_netif = netif_get_adpt_netif(LWIP_NETIF_TYPE_WAN_WIFI);
if(wifi_cli_netif != NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkup_callback_2, P_INFO, 0, "wifi wan has linkup");
return ERR_OK;
}
// alloc netif structure
wifi_cli_netif = mem_malloc(sizeof(struct netif));
if (wifi_cli_netif == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkup_callback_mem_1, P_WARNING, 0,
"LAN link type %u, can't alloc mem for netif");
return ERR_MEM;
}
memset(wifi_cli_netif, 0, sizeof(struct netif));
wifi_cli_netif->primary_ipv4_cid = LWIP_PS_INVALID_CID;
wifi_cli_netif->primary_ipv6_cid = LWIP_PS_INVALID_CID;
/* init netif mtu, MTU size suggest could config by AT - TBD */
wifi_cli_netif->mtu = (conf->mtu == 0)?LAN_NETIF_DEFAULT_MTU : conf->mtu;
if(conf->ipv4NetMaskPresent)
{
ip4_addr_copy(wifi_netif_netmask, conf->ipv4NetMask);
}
else
{
IP4_ADDR(&wifi_netif_netmask, 255, 255, 255, 255);
}
//register LAN netif to tcpip stack
netif_add(wifi_cli_netif, IP4_ADDR_ANY4, &wifi_netif_netmask, IP4_ADDR_ANY4, NULL, wifi_cli_netif_init, NULL);
/* set the wan type */
netif_set_netif_type(wifi_cli_netif, LWIP_NETIF_TYPE_WAN_WIFI);
netif_set_link_up(wifi_cli_netif);
//ipv4
if(conf->ipType == NM_NET_TYPE_IPV4 || conf->ipType == NM_NET_TYPE_IPV4V6)
{
//set ipv4 address
netif_set_ipaddr(wifi_cli_netif, &conf->ipv4Addr);
//set ipv4 dns server
if(conf->dnsNum > 0)
{
for (i = 0; i < conf->dnsNum; i++)
{
if(IP_IS_V4_VAL(conf->dns[i]) &&
(!ip_addr_isany(&conf->dns[i])))
{
dns_setserver(wifi_cli_netif, &conf->dns[i]);
}
}
}
netif_set_type_up(wifi_cli_netif, NETIF_REPORT_TYPE_IPV4);
}
//ipv6
if(conf->ipType == NM_NET_TYPE_IPV6 || conf->ipType == NM_NET_TYPE_IPV4V6)
{
//set ipv6 linklocal address
netif_ip6_addr_set(wifi_cli_netif, 0, &conf->ipv6LinkLocalAddr);
netif_ip6_addr_set_state(wifi_cli_netif, 0, IP6_ADDR_VALID);
//set ipv6 global address
netif_ip6_addr_set(wifi_cli_netif, 1, &conf->ipv6GlobalAddr);
/* Set address state. */
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
/* Will perform duplicate address detection (DAD). */
netif_ip6_addr_set_state(wifi_cli_netif, 1, IP6_ADDR_TENTATIVE);
#else
/* Consider address valid. */
netif_ip6_addr_set_state(wifi_cli_netif, 1, IP6_ADDR_PREFERRED);
#endif
//set ipv6 dns server
if(conf->dnsNum > 0)
{
for (i = 0; i < conf->dnsNum; i++)
{
if(IP_IS_V6_VAL(conf->dns[i]) &&
(!ip_addr_isany(&conf->dns[i])))
{
dns_setserver(wifi_cli_netif, &conf->dns[i]);
}
}
}
netif_set_type_up(wifi_cli_netif, NETIF_REPORT_TYPE_IPV6);
}
//set default
if(conf->bDefault)
{
netif_set_default(wifi_cli_netif);
}
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkup_callback_3, P_INFO, 0, "wifi cli wan linkup");
return ERR_OK;
}
/******************************************************************************
* wifi_client_wan_linkdown_callback
* Description: wifi client wan linkdown call back
* input:
* output:
* Comment:
*
******************************************************************************/
err_t wifi_client_wan_linkdown_callback(void)
{
struct netif *wifi_cli_netif = NULL;
//check whether wifi wan has linkup
wifi_cli_netif = netif_get_adpt_netif(LWIP_NETIF_TYPE_WAN_WIFI);
if(wifi_cli_netif == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkdown_callback_1, P_INFO, 0, "wifi cli wan has linkdown");
return ERR_OK;
}
dns_clearserver(wifi_cli_netif, IPADDR_TYPE_V4);
dns_clearserver(wifi_cli_netif ,IPADDR_TYPE_V6);
#if LINK_DOWN_NEED_CLEAR_DNS_CACHE
dns_clear_cache(IPADDR_TYPE_V4);
dns_clear_cache(IPADDR_TYPE_V6);
#endif
netif_remove(wifi_cli_netif);
mem_free(wifi_cli_netif);
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_linkdown_callback_2, P_INFO, 0, "wifi cli wan linkdown");
return ERR_OK;
}
/******************************************************************************
* wifi_client_wan_default_route_change_callback
* Description: wifi client wan default route change call back
* input:
* output:
* Comment:
*
******************************************************************************/
err_t wifi_client_wan_default_route_change_callback(NmWanNetDefaultChangeInfo *pInfo)
{
struct netif *netif = NULL;
if(pInfo == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_1, P_ERROR, 0, "invalid argu");
return ERR_ARG;
}
else if(pInfo->type != NM_WAN_NET_PS_CAT1 && pInfo->type != NM_WAN_NET_WIFI_CLI)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_type_1, P_ERROR, 1, "invalid type %u", pInfo->type);
return ERR_ARG;
}
if(pInfo->type == NM_WAN_NET_PS_CAT1)
{
if(LWIP_CHECK_CID_VALID(pInfo->cid))
{
netif = netif_find_by_cid(pInfo->cid);
if(netif == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_2, P_ERROR, 1, "can not find netif by cid %u", pInfo->cid);
return ERR_ARG;
}
else
{
netif_set_default(netif);
}
}
else
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_3, P_ERROR, 1, "invalid cid %u", pInfo->cid);
return ERR_ARG;
}
}
else if(pInfo->type == NM_WAN_NET_WIFI_CLI)
{
netif = netif_get_adpt_netif(LWIP_NETIF_TYPE_WAN_WIFI);
if(netif == NULL)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_4, P_ERROR, 0, "can not find wifi client netif");
return ERR_ARG;
}
else
{
netif_set_default(netif);
}
}
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_client_wan_default_route_change_callback_5, P_INFO, 2, "wifi wan default change to type %u ,cid &u", pInfo->type, pInfo->cid);
return ERR_OK;
}
/******************************************************************************
* wifi_cli_wan_tcpip_input
* Description:
* input: u8_t wanType, UlPduBlock *pPduHdr
* output:UINT8
* Comment:
******************************************************************************/
err_t wifi_cli_wan_tcpip_input(u8_t wanType)
{
struct netif *inp = PNULL;
struct pbuf *p = PNULL;
UlPduBlock *pUlPduTmp = PNULL, *pUlPduTmpNext = PNULL;
UlPduBlock *pOnePkgHead = PNULL, *pOnePkgTail = PNULL;
UINT16 pduTotalLen = 0;
UlPduBlock *pPduHdr = PNULL;
OsaDebugBegin(wanType == LWIP_NETIF_TYPE_WAN_WIFI, 0, wanType, 0);
return ERR_ARG;
OsaDebugEnd();
wifi_cli_ulPkg_ListGet(&pPduHdr);
inp = netif_get_adpt_netif(LWIP_NETIF_TYPE_WAN_WIFI);
if (inp == PNULL)
{
ECOMM_TRACE_I(UNILOG_TCPIP_NETADPT, wifi_cli_wan_tcpip_input_1, P_ERROR, 0,
"wifi cli netif recv wan pkg, but can not find adpt netif, type %u", wanType);
if(pPduHdr != PNULL)
{
OsaFreeUlPduBlockList(&pPduHdr);
}
return ERR_ARG;
}
for (pUlPduTmp = pPduHdr; pUlPduTmp != PNULL;)
{
pUlPduTmpNext = NetifUlGetOnePkg(pUlPduTmp, &pOnePkgHead, &pOnePkgTail, &pduTotalLen);
//ToDo:could improve(zero copy)
p = pbuf_alloc(PBUF_RAW, pduTotalLen, PBUF_RAM);
if (p == PNULL)
{
ECOMM_TRACE_I(UNILOG_TCPIP_NETADPT, wifi_cli_wan_tcpip_input_2, P_ERROR, 1,
"wifi cli recv wan pkg, but allocate pbuf free, dicard the pkglen: %d", pduTotalLen);
OsaFreeUlPduBlockList(&pUlPduTmp);
pUlPduTmp = pUlPduTmpNext;
continue;
}
else
{
p->tot_len = NetifCopyDataFromUlPdu(p->payload, pUlPduTmp);
OsaFreeUlPduBlockList(&pUlPduTmp);
}
//dump pkg for debug
netif_dump_dl_packet(p->payload, p->tot_len, LWIP_NETIF_TYPE_WAN_INTERNET);
ps_ip_input(p, inp);
pUlPduTmp = pUlPduTmpNext;
}
return ERR_OK;
}
/******************************************************************************
* wifi_cli_wan_recv_ul_pkg
* Description: wifi client wan netif low level input function
* input: void
* output:
* Comment:
******************************************************************************/
err_t wifi_cli_wan_pkg_notify(void)
{
err_t ret;
ret = TcpipWanInpkt(LWIP_NETIF_TYPE_WAN_WIFI, wifi_cli_wan_tcpip_input);
if (ret != ERR_OK)
{
ECOMM_TRACE(UNILOG_TCPIP_NETADPT, wifi_cli_wan_pkg_notify_1, P_ERROR, 1,
"wifi_cli_wan_pkg_notify fail");
return ret; //msg memory alloc fail or can not find netif by lcid
}
return ERR_OK;
}
/******************************************************************************
* wifi_cli_ul_listinput
* Description:
* input:
* output:
* Comment:
*
******************************************************************************/
void wifi_cli_ul_listinput(UINT16 pkgNum, UlPduBlock *pHead, UlPduBlock *pTail)
{
UINT32 mask = 0, inIsr = osIsInISRContext(), needNotify = 0;
WifiCliUlPkgPendingList *pPendingList = PNULL;
OsaCheck(pHead != PNULL && pTail != PNULL && pTail->pNext == PNULL && pkgNum > 0,
pHead, pTail, pkgNum);
if (!inIsr)
{
mask = SaveAndSetIRQMask();
}
pPendingList = &gWifiCliUlpkgPendingList;
//OsaCheck(pPendingList != PNULL, cid, 0, 0);
if(pPendingList->pHead == PNULL)
{
needNotify = 1;
}
/* Link */
UlPduAddList(&pPendingList->pHead, &pPendingList->pTail, pHead, pTail);
pPendingList->pkgNum += pkgNum;
if (!inIsr)
{
RestoreIRQMask(mask);
}
if (needNotify)
{
wifi_cli_wan_pkg_notify();
}
return;
}
void wifi_cli_output_set_cust_func(BOOL isRegister, wifiCliOutputFunc custOutputFunc)
{
if(isRegister)
wifiOutPutCustFunc = custOutputFunc;
else
wifiOutPutCustFunc = NULL;
}
#endif