diff --git a/APP_Framework/Applications/connection_app/Makefile b/APP_Framework/Applications/connection_app/Makefile index 0cb8c9568..df4ae9b97 100755 --- a/APP_Framework/Applications/connection_app/Makefile +++ b/APP_Framework/Applications/connection_app/Makefile @@ -1,6 +1,3 @@ - -ifeq ($(CONFIG_SOCKET_DEMO),y) - include $(KERNEL_ROOT)/.config ifeq ($(CONFIG_ADD_NUTTX_FETURES),y) @@ -21,4 +18,3 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) include $(KERNEL_ROOT)/compiler.mk endif -endif diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c index b6e4f9428..48f147fe9 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c @@ -21,7 +21,7 @@ #include #ifdef ADD_XIZI_FETURES -#include "sys_arch.h" +#include #include #include "lwip/sys.h" #endif @@ -33,9 +33,17 @@ #include "stdio.h" #endif -#define TCP_DEMO_BUF_SIZE 65535 +#define TCP_DEMO_BUF_SIZE 65535 +#define TCP_DEMO_SEND_TIMES 20 +#define LWIP_TCP_DEMO_TASK_STACK_SIZE 4096 +#define LWIP_TCP_DEMO_TASK_PRIO 20 -char tcp_socket_ip[] = {192, 168, 250, 252}; +static pthread_t tcp_client_task; +static pthread_t tcp_server_task; + +static char tcp_demo_ipaddr[] = {192, 168, 131, 77}; +static char tcp_demo_netmask[] = {255, 255, 254, 0}; +static char tcp_demo_gwaddr[] = {192, 168, 131, 1}; #ifdef ADD_NUTTX_FETURES #define lw_print printf @@ -46,8 +54,8 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; #define LWIP_TARGET_PORT 4840 #endif -uint16_t tcp_socket_port = LWIP_TARGET_PORT; -char tcp_ip_str[128] = {0}; +static uint16_t tcp_socket_port = 8888; +static char tcp_ip_str[128] = {0}; /******************************************************************************/ void TcpSocketConfigParam(char *ip_str) @@ -55,35 +63,23 @@ void TcpSocketConfigParam(char *ip_str) int ip1, ip2, ip3, ip4, port = 0; if(ip_str == NULL) - { return; - } - if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) - { + if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) { printf("config ip %s port %d\n", ip_str, port); strcpy(tcp_ip_str, ip_str); - tcp_socket_ip[0] = ip1; - tcp_socket_ip[1] = ip2; - tcp_socket_ip[2] = ip3; - tcp_socket_ip[3] = ip4; if(port) tcp_socket_port = port; return; } - if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) - { + if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) { printf("config ip %s\n", ip_str); - tcp_socket_ip[0] = ip1; - tcp_socket_ip[1] = ip2; - tcp_socket_ip[2] = ip3; - tcp_socket_ip[3] = ip4; strcpy(tcp_ip_str, ip_str); } } -static void TcpSocketRecvTask(void *arg) +static void *TcpSocketRecvTask(void *arg) { int fd = -1, clientfd; int recv_len; @@ -91,18 +87,15 @@ static void TcpSocketRecvTask(void *arg) struct sockaddr_in tcp_addr; socklen_t addr_len; - while(1) - { + while(1) { recv_buf = (char *)malloc(TCP_DEMO_BUF_SIZE); - if (recv_buf == NULL) - { + if (recv_buf == NULL) { lw_error("No memory\n"); continue; } fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - { + if (fd < 0) { lw_error("Socket error\n"); free(recv_buf); continue; @@ -113,8 +106,7 @@ static void TcpSocketRecvTask(void *arg) tcp_addr.sin_port = htons(tcp_socket_port); memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero)); - if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) - { + if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) { lw_error("Unable to bind\n"); close(fd); free(recv_buf); @@ -125,8 +117,7 @@ static void TcpSocketRecvTask(void *arg) lw_notice("\nLocal Port:%d\n", tcp_socket_port); // setup socket fd as listening mode - if (listen(fd, 5) != 0 ) - { + if (listen(fd, 5) != 0 ) { lw_error("Unable to listen\n"); close(fd); free(recv_buf); @@ -137,13 +128,11 @@ static void TcpSocketRecvTask(void *arg) clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); lw_notice("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); - while(1) - { + while(1) { memset(recv_buf, 0, TCP_DEMO_BUF_SIZE); recv_len = recvfrom(clientfd, recv_buf, TCP_DEMO_BUF_SIZE, 0, (struct sockaddr *)&tcp_addr, &addr_len); - if(recv_len > 0) - { + if(recv_len > 0) { lw_notice("Receive from : %s\n", inet_ntoa(tcp_addr.sin_addr)); lw_notice("Receive data : %d - %s\n\n", recv_len, recv_buf); } @@ -157,26 +146,33 @@ static void TcpSocketRecvTask(void *arg) void TcpSocketRecvTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); TcpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip); - sys_thread_new("TcpSocketRecvTask", TcpSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - TcpSocketRecvTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&tcp_server_task, &attr, &TcpSocketRecvTask, NULL); + PrivTaskStartup(&tcp_server_task); } PRIV_SHELL_CMD_FUNCTION(TcpSocketRecvTest, a tcp receive sample, PRIV_SHELL_CMD_MAIN_ATTR); -static void TcpSocketSendTask(void *arg) +static void *TcpSocketSendTask(void *arg) { - int cnt = LWIP_DEMO_TIMES; + int cnt = TCP_DEMO_SEND_TIMES; int fd = -1; int ret; char send_msg[128]; @@ -186,10 +182,9 @@ static void TcpSocketSendTask(void *arg) memset(send_msg, 0, sizeof(send_msg)); fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - { + if (fd < 0) { lw_print("Socket error\n"); - return; + return NULL; } struct sockaddr_in tcp_sock; @@ -200,17 +195,15 @@ static void TcpSocketSendTask(void *arg) memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr)); - if (ret) - { - lw_print("Unable to connect %s = %d\n", tcp_ip_str, ret); + if (ret < 0) { + lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret); close(fd); - return; + return NULL; } lw_print("TCP connect %s:%d success, start to send.\n", tcp_ip_str, tcp_socket_port); - while (cnt --) - { + while (cnt --) { lw_print("Lwip client is running.\n"); snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt); send(fd, send_msg, strlen(send_msg), 0); @@ -219,24 +212,31 @@ static void TcpSocketSendTask(void *arg) } close(fd); - return; + return NULL; } void TcpSocketSendTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); TcpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip); - sys_thread_new("Tcp Socket Send", TcpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - TcpSocketSendTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&tcp_client_task, &attr, &TcpSocketSendTask, NULL); + PrivTaskStartup(&tcp_client_task); } PRIV_SHELL_CMD_FUNCTION(TcpSocketSendTest, a tcp send sample, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c index 51c94a6c3..30a8a6a59 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c @@ -20,7 +20,7 @@ #include #ifdef ADD_XIZI_FETURES -#include "sys_arch.h" +#include #include "lwip/sockets.h" #endif @@ -38,11 +38,20 @@ #define lw_print printf #endif -#define UDP_BUF_SIZE 65536 +#define UDP_DEMO_BUF_SIZE 65535 +#define UDP_DEMO_SEND_TIMES 20 +#define LWIP_UDP_DEMO_TASK_STACK_SIZE 4096 +#define LWIP_UDP_DEMO_TASK_PRIO 20 -char udp_socket_ip[] = {192, 168, 250, 252}; -char udp_ip_str[128] = {0}; -uint16_t udp_socket_port = LWIP_LOCAL_PORT; +static pthread_t udp_client_task; +static pthread_t udp_server_task; + +static char udp_demo_ipaddr[] = {192, 168, 131, 77}; +static char udp_demo_netmask[] = {255, 255, 254, 0}; +static char udp_demo_gwaddr[] = {192, 168, 131, 1}; + +static char udp_ip_str[128] = {0}; +static uint16_t udp_socket_port = 8888; /*****************************************************************************/ void UdpSocketConfigParam(char *ip_str) @@ -50,53 +59,38 @@ void UdpSocketConfigParam(char *ip_str) int ip1, ip2, ip3, ip4, port = 0; if(ip_str == NULL) - { return; - } - if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) - { + if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) { printf("config ip %s port %d\n", ip_str, port); strcpy(udp_ip_str, ip_str); - udp_socket_ip[0] = ip1; - udp_socket_ip[1] = ip2; - udp_socket_ip[2] = ip3; - udp_socket_ip[3] = ip4; if(port) udp_socket_port = port; return; } - if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) - { + if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) { printf("config ip %s\n", ip_str); - udp_socket_ip[0] = ip1; - udp_socket_ip[1] = ip2; - udp_socket_ip[2] = ip3; - udp_socket_ip[3] = ip4; strcpy(udp_ip_str, ip_str); } } -static void UdpSocketRecvTask(void *arg) +static void *UdpSocketRecvTask(void *arg) { int fd = -1; char *recv_buf; struct sockaddr_in udp_addr, server_addr; int recv_len; - while(1) - { - recv_buf = (char *)malloc(UDP_BUF_SIZE); - if(recv_buf == NULL) - { + while(1) { + recv_buf = (char *)PrivMalloc(UDP_DEMO_BUF_SIZE); + if(recv_buf == NULL) { lw_error("No memory\n"); continue; } fd = socket(AF_INET, SOCK_DGRAM, 0); - if(fd < 0) - { + if(fd < 0) { lw_error("Socket error\n"); free(recv_buf); continue; @@ -107,8 +101,7 @@ static void UdpSocketRecvTask(void *arg) udp_addr.sin_port = htons(udp_socket_port); memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero)); - if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) - { + if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) { lw_error("Unable to bind\n"); close(fd); free(recv_buf); @@ -118,12 +111,10 @@ static void UdpSocketRecvTask(void *arg) lw_notice("UDP bind success, start to receive.\n"); lw_notice("\n\nLocal Port:%d\n\n", udp_socket_port); - while(1) - { - memset(recv_buf, 0, UDP_BUF_SIZE); - recv_len = recv(fd, recv_buf, UDP_BUF_SIZE, 0); - if(recv_len > 0) - { + while(1) { + memset(recv_buf, 0, UDP_DEMO_BUF_SIZE); + recv_len = recv(fd, recv_buf, UDP_DEMO_BUF_SIZE, 0); + if(recv_len > 0) { lw_notice("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); lw_notice("Receive data : %s\n\n", recv_buf); } @@ -137,36 +128,41 @@ static void UdpSocketRecvTask(void *arg) void UdpSocketRecvTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]); UdpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip); - sys_thread_new("UdpSocketRecvTask", UdpSocketRecvTask, NULL, - LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - UdpSocketRecvTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&udp_server_task, &attr, &UdpSocketRecvTask, NULL); + PrivTaskStartup(&udp_server_task); } PRIV_SHELL_CMD_FUNCTION(UdpSocketRecvTest, a udp receive sample, PRIV_SHELL_CMD_MAIN_ATTR); -static void UdpSocketSendTask(void *arg) +static void *UdpSocketSendTask(void *arg) { - int cnt = LWIP_DEMO_TIMES; + int cnt = UDP_DEMO_SEND_TIMES; char send_str[128]; int fd = -1; memset(send_str, 0, sizeof(send_str)); fd = socket(AF_INET, SOCK_DGRAM, 0); - if(fd < 0) - { + if(fd < 0) { lw_error("Socket error\n"); - return; + return NULL; } struct sockaddr_in udp_sock; @@ -175,19 +171,17 @@ static void UdpSocketSendTask(void *arg) udp_sock.sin_addr.s_addr = inet_addr(udp_ip_str); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); - if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) - { - lw_error("Unable to connect\n"); + if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)) < 0) { + lw_error("Unable to connect %s:%d\n", udp_ip_str, udp_socket_port); close(fd); - return; + return NULL; } lw_print("UDP connect %s:%d success, start to send.\n", udp_ip_str, udp_socket_port); - while(cnt --) - { + while(cnt --) { snprintf(send_str, sizeof(send_str), "UDP test package times %d\r\n", cnt); send(fd, send_str, strlen(send_str), 0); lw_notice("Send UDP msg: %s ", send_str); @@ -195,25 +189,31 @@ static void UdpSocketSendTask(void *arg) } close(fd); - return; + return NULL; } void UdpSocketSendTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]); UdpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip); - sys_thread_new("UdpSocketSendTask", UdpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, - LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - UdpSocketSendTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&udp_client_task, &attr, &UdpSocketSendTask, NULL); + PrivTaskStartup(&udp_client_task); } PRIV_SHELL_CMD_FUNCTION(UdpSocketSendTest, a udp send sample, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c index c50831630..f792d669f 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c @@ -39,7 +39,8 @@ Modification: 3、add ETH_RST_PORT and ETH_RST_PIN; 4、add ETH_LINK_LED_PORT and ETH_LINK_LED_PIN; 5、add ethernetif_config_enet_set; -6、add ETHERNET_LOOPBACK_TEST with testnetif and txPbuf. +6、add ETHERNET_LOOPBACK_TEST with testnetif and txPbuf; +7、modify ethernetif_init() and ethernetif_input() to support LwIP. *************************************************/ /******************************************************************************* @@ -282,6 +283,10 @@ static int32_t low_level_init(struct netif *netif) netif->hwaddr[5] = (EthHandle.stcCommInit).au8MacAddr[5]; /* maximum transfer unit */ netif->mtu = 1500U; + + /* device capabilities */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + /* Enable MAC and DMA transmission and reception */ (void)ETH_Start(); @@ -322,9 +327,9 @@ static int32_t low_level_init(struct netif *netif) * - LL_OK: The packet could be sent * - LL_ERR: The packet couldn't be sent */ -int32_t low_level_output(struct netif *netif, struct pbuf *p) +err_t low_level_output(struct netif *netif, struct pbuf *p) { - int32_t i32Ret; + err_t i32Ret; struct pbuf *q; uint8_t *txBuffer; __IO stc_eth_dma_desc_t *DmaTxDesc; @@ -474,8 +479,22 @@ static struct pbuf *low_level_input(struct netif *netif) */ err_t ethernetif_init(struct netif *netif) { +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; + +#ifndef ETHERNET_LOOPBACK_TEST + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = ðarp_output; + netif->linkoutput = &low_level_output; +#endif + /* initialize the hardware */ return low_level_init(netif); } @@ -487,15 +506,32 @@ err_t ethernetif_init(struct netif *netif) */ void ethernetif_input(struct netif *netif) { + err_t err; struct pbuf *p; /* Move received packet into a new pbuf */ p = low_level_input(netif); + +#ifndef ETHERNET_LOOPBACK_TEST + /* No packet could be read, silently ignore this */ + if (NULL == p) { + return; + } + + /* Entry point to the LwIP stack */ + err = netif->input(p, netif); + if (err != (err_t)ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + (void)pbuf_free(p); + } +#endif +#ifdef ETHERNET_LOOPBACK_TEST /* No packet could be read, silently ignore this */ if (p != NULL) { EthernetIF_InputCallback(netif, p); free(p); } +#endif } /** diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h index 0fb839584..e07b5495e 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h @@ -135,7 +135,7 @@ extern "C" */ err_t ethernetif_init(struct netif *netif); void ethernetif_input(struct netif *netif); -int32_t low_level_output(struct netif *netif, struct pbuf *p); +err_t low_level_output(struct netif *netif, struct pbuf *p); void EthernetIF_CheckLink(struct netif *netif); void EthernetIF_UpdateLink(struct netif *netif);