9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
347 lines
11 KiB
C
347 lines
11 KiB
C
/*!
|
|
\file netconf.c
|
|
\brief network connection configuration
|
|
|
|
\version 2025-02-19, V2.1.0, demo for GD32H7xx
|
|
*/
|
|
|
|
/*
|
|
Copyright (c) 2024, GigaDevice Semiconductor Inc.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
3. Neither the name of the copyright holder nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software without
|
|
specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "lwip/mem.h"
|
|
#include "lwip/memp.h"
|
|
#include "lwip/dhcp.h"
|
|
#include "lwip/dns.h"
|
|
#include "ethernetif.h"
|
|
#include "main.h"
|
|
#include "netconf.h"
|
|
#include "publicdata/publicdata.h"
|
|
#include "lwip/tcpip.h"
|
|
#include <stdio.h>
|
|
#include "lwip/errno.h"
|
|
#include "queue.h"
|
|
|
|
#define DHCP_TRIES_MAX_TIMES 3
|
|
|
|
int errno;
|
|
|
|
typedef enum
|
|
{
|
|
DHCP_ADDR_NONE = 0,
|
|
DHCP_ADDR_BEGIN,
|
|
DHCP_ADDR_GOT,
|
|
DHCP_ADDR_FAIL
|
|
}dhcp_addr_status_enum;
|
|
|
|
#ifdef USE_DHCP
|
|
dhcp_addr_status_enum dhcp_state = DHCP_ADDR_NONE;
|
|
#endif /* USE_DHCP */
|
|
|
|
#ifdef USE_ENET0
|
|
struct netif g_mynetif0;
|
|
#endif /* USE_ENET0 */
|
|
#ifdef USE_ENET1
|
|
struct netif g_mynetif1;
|
|
#endif /* USE_ENET1 */
|
|
|
|
ip_addr_t ip_address = {0};
|
|
|
|
static uint8_t netconf_is_all_value(const U8_T *buf, U8_T value)
|
|
{
|
|
return (uint8_t)((buf[0] == value) && (buf[1] == value) && (buf[2] == value) && (buf[3] == value));
|
|
}
|
|
|
|
static uint8_t netconf_is_valid_host_ip(const U8_T *ip)
|
|
{
|
|
if (netconf_is_all_value(ip, 0x00U) || netconf_is_all_value(ip, 0xFFU)) {
|
|
return 0U;
|
|
}
|
|
if ((ip[0] == 0U) || (ip[0] == 127U) || (ip[0] >= 224U)) {
|
|
return 0U;
|
|
}
|
|
return 1U;
|
|
}
|
|
|
|
static uint8_t netconf_is_valid_netmask(const U8_T *mask)
|
|
{
|
|
uint32_t m;
|
|
uint8_t seen_zero = 0U;
|
|
|
|
if (netconf_is_all_value(mask, 0x00U) || netconf_is_all_value(mask, 0xFFU)) {
|
|
return 0U;
|
|
}
|
|
|
|
m = ((uint32_t)mask[0] << 24) | ((uint32_t)mask[1] << 16) | ((uint32_t)mask[2] << 8) | (uint32_t)mask[3];
|
|
for (uint32_t bit = 0U; bit < 32U; bit++) {
|
|
uint8_t cur = (uint8_t)((m >> (31U - bit)) & 0x1U);
|
|
if (cur == 0U) {
|
|
seen_zero = 1U;
|
|
} else if (seen_zero != 0U) {
|
|
return 0U;
|
|
}
|
|
}
|
|
return 1U;
|
|
}
|
|
|
|
static uint8_t netconf_is_same_subnet(const U8_T *ip, const U8_T *gw, const U8_T *mask)
|
|
{
|
|
uint32_t ip32 = ((uint32_t)ip[0] << 24) | ((uint32_t)ip[1] << 16) | ((uint32_t)ip[2] << 8) | (uint32_t)ip[3];
|
|
uint32_t gw32 = ((uint32_t)gw[0] << 24) | ((uint32_t)gw[1] << 16) | ((uint32_t)gw[2] << 8) | (uint32_t)gw[3];
|
|
uint32_t m32 = ((uint32_t)mask[0] << 24) | ((uint32_t)mask[1] << 16) | ((uint32_t)mask[2] << 8) | (uint32_t)mask[3];
|
|
return (uint8_t)(((ip32 & m32) == (gw32 & m32)) ? 1U : 0U);
|
|
}
|
|
|
|
static void netconf_get_static_ip_from_cfg(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw)
|
|
{
|
|
const U8_T *cfg_ip = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_ip;
|
|
const U8_T *cfg_mask = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_mask;
|
|
const U8_T *cfg_gw = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_gate;
|
|
uint8_t use_cfg = 1U;
|
|
|
|
if (netconf_is_valid_host_ip(cfg_ip) == 0U) {
|
|
use_cfg = 0U;
|
|
}
|
|
if (netconf_is_valid_host_ip(cfg_gw) == 0U) {
|
|
use_cfg = 0U;
|
|
}
|
|
if (netconf_is_valid_netmask(cfg_mask) == 0U) {
|
|
use_cfg = 0U;
|
|
}
|
|
if ((use_cfg != 0U) && (netconf_is_same_subnet(cfg_ip, cfg_gw, cfg_mask) == 0U)) {
|
|
use_cfg = 0U;
|
|
}
|
|
|
|
if (use_cfg != 0U) {
|
|
IP4_ADDR(ip, cfg_ip[0], cfg_ip[1], cfg_ip[2], cfg_ip[3]);
|
|
IP4_ADDR(mask, cfg_mask[0], cfg_mask[1], cfg_mask[2], cfg_mask[3]);
|
|
IP4_ADDR(gw, cfg_gw[0], cfg_gw[1], cfg_gw[2], cfg_gw[3]);
|
|
printf("[NETCONF] static ip from cfg: %u.%u.%u.%u, mask=%u.%u.%u.%u, gw=%u.%u.%u.%u\r\n",
|
|
cfg_ip[0], cfg_ip[1], cfg_ip[2], cfg_ip[3],
|
|
cfg_mask[0], cfg_mask[1], cfg_mask[2], cfg_mask[3],
|
|
cfg_gw[0], cfg_gw[1], cfg_gw[2], cfg_gw[3]);
|
|
} else {
|
|
IP4_ADDR(ip, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
|
|
IP4_ADDR(mask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
|
|
IP4_ADDR(gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
|
|
printf("[NETCONF] cfg ip invalid, fallback board ip: %u.%u.%u.%u\r\n",
|
|
BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief after the netif is fully configured, it will be called to initialize the function of telnet, client and udp
|
|
\param[in] netif: the struct used for lwIP network interface
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void lwip_netif_status_callback(struct netif *netif)
|
|
{
|
|
if(((netif->flags & NETIF_FLAG_UP) != 0) && (0 != netif->ip_addr.addr)) {
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief initializes the LwIP stack
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void lwip_stack_init(void)
|
|
{
|
|
ip_addr_t gd_ipaddr;
|
|
ip_addr_t gd_netmask;
|
|
ip_addr_t gd_gw;
|
|
|
|
/* create tcp_ip stack thread */
|
|
tcpip_init(NULL, NULL);
|
|
|
|
/* IP address setting */
|
|
#ifdef USE_DHCP
|
|
gd_ipaddr.addr = 0;
|
|
gd_netmask.addr = 0;
|
|
gd_gw.addr = 0;
|
|
#else
|
|
netconf_get_static_ip_from_cfg(&gd_ipaddr, &gd_netmask, &gd_gw);
|
|
#endif /* USE_DHCP */
|
|
|
|
#ifdef USE_ENET0
|
|
/* add a new network interface */
|
|
netif_add(&g_mynetif0, &gd_ipaddr, &gd_netmask, &gd_gw, NULL, ðernetif_init, &tcpip_input);
|
|
|
|
/* set a default network interface */
|
|
netif_set_default(&g_mynetif0);
|
|
|
|
/* set a callback when interface is up/down */
|
|
netif_set_status_callback(&g_mynetif0, lwip_netif_status_callback);
|
|
|
|
/* set the flag of netif as NETIF_FLAG_LINK_UP */
|
|
netif_set_link_up(&g_mynetif0);
|
|
|
|
/* bring an interface up and set the flag of netif as NETIF_FLAG_UP */
|
|
netif_set_up(&g_mynetif0);
|
|
|
|
#if LWIP_DNS
|
|
/* 静态 IP 时无 DHCP 下发 DNS,需手动设置 */
|
|
{
|
|
ip_addr_t dns_server;
|
|
IP_ADDR4(&dns_server, 114, 114, 114, 114);
|
|
dns_setserver(0, &dns_server);
|
|
}
|
|
#endif /* LWIP_DNS */
|
|
#endif /* USE_ENET0 */
|
|
|
|
#ifdef USE_ENET1
|
|
/* add a new network interface */
|
|
netif_add(&g_mynetif1, &gd_ipaddr, &gd_netmask, &gd_gw, NULL, ðernetif_init, &tcpip_input);
|
|
|
|
/* set a default network interface */
|
|
netif_set_default(&g_mynetif1);
|
|
|
|
/* set a callback when interface is up/down */
|
|
netif_set_status_callback(&g_mynetif1, lwip_netif_status_callback);
|
|
|
|
/* set the flag of netif as NETIF_FLAG_LINK_UP */
|
|
netif_set_link_up(&g_mynetif1);
|
|
|
|
/* bring an interface up and set the flag of netif as NETIF_FLAG_UP */
|
|
netif_set_up(&g_mynetif1);
|
|
|
|
#if LWIP_DNS
|
|
{
|
|
ip_addr_t dns_server;
|
|
IP_ADDR4(&dns_server, 114, 114, 114, 114);
|
|
dns_setserver(0, &dns_server);
|
|
}
|
|
#endif /* LWIP_DNS */
|
|
#endif /* USE_ENET1 */
|
|
}
|
|
|
|
#ifdef USE_DHCP
|
|
/*!
|
|
\brief dhcp_task
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void dhcp_task(void * pvParameters)
|
|
{
|
|
ip_addr_t gd_ipaddr;
|
|
ip_addr_t gd_netmask;
|
|
ip_addr_t gd_gw;
|
|
|
|
#ifdef USE_ENET0
|
|
struct dhcp *dhcp_client0;
|
|
#endif /* USE_ENET0 */
|
|
#ifdef USE_ENET1
|
|
struct dhcp *dhcp_client1;
|
|
#endif /* USE_ENET1 */
|
|
|
|
for(;;){
|
|
#ifdef USE_ENET0
|
|
switch(dhcp_state){
|
|
case DHCP_ADDR_NONE:
|
|
dhcp_start(&g_mynetif0);
|
|
/* IP address should be set to 0 every time we want to assign a new DHCP address*/
|
|
ip_address.addr = 0;
|
|
dhcp_state = DHCP_ADDR_BEGIN;
|
|
break;
|
|
|
|
case DHCP_ADDR_BEGIN:
|
|
/* got the IP address */
|
|
ip_address.addr = g_mynetif0.ip_addr.addr;
|
|
|
|
if(0 != ip_address.addr){
|
|
dhcp_state = DHCP_ADDR_GOT;
|
|
printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), \
|
|
ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
|
|
}else{
|
|
/* DHCP timeout */
|
|
dhcp_client0 = netif_dhcp_data(&g_mynetif0);
|
|
if(dhcp_client0->tries > DHCP_TRIES_MAX_TIMES){
|
|
dhcp_state = DHCP_ADDR_FAIL;
|
|
/* stop DHCP */
|
|
dhcp_stop(&g_mynetif0);
|
|
|
|
/* use static address as IP address */
|
|
IP4_ADDR(&gd_ipaddr, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
|
|
IP4_ADDR(&gd_netmask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
|
|
IP4_ADDR(&gd_gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
|
|
netif_set_addr(&g_mynetif0, &gd_ipaddr, &gd_netmask, &gd_gw);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#endif /* USE_ENET0 */
|
|
#ifdef USE_ENET1
|
|
switch(dhcp_state){
|
|
case DHCP_ADDR_NONE:
|
|
dhcp_start(&g_mynetif1);
|
|
/* IP address should be set to 0 every time we want to assign a new DHCP address*/
|
|
ip_address.addr = 0;
|
|
dhcp_state = DHCP_ADDR_BEGIN;
|
|
break;
|
|
|
|
case DHCP_ADDR_BEGIN:
|
|
/* got the IP address */
|
|
ip_address.addr = g_mynetif1.ip_addr.addr;
|
|
|
|
if(0 != ip_address.addr){
|
|
dhcp_state = DHCP_ADDR_GOT;
|
|
printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), \
|
|
ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
|
|
}else{
|
|
/* DHCP timeout */
|
|
dhcp_client1 = netif_dhcp_data(&g_mynetif1);
|
|
if(dhcp_client1->tries > DHCP_TRIES_MAX_TIMES){
|
|
dhcp_state = DHCP_ADDR_FAIL;
|
|
/* stop DHCP */
|
|
dhcp_stop(&g_mynetif1);
|
|
|
|
/* use static address as IP address */
|
|
IP4_ADDR(&gd_ipaddr, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
|
|
IP4_ADDR(&gd_netmask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
|
|
IP4_ADDR(&gd_gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
|
|
netif_set_addr(&g_mynetif1, &gd_ipaddr, &gd_netmask, &gd_gw);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#endif /* USE_ENET1 */
|
|
/* wait 250 ms */
|
|
vTaskDelay(250);
|
|
}
|
|
}
|
|
#endif /* USE_DHCP */
|
|
|
|
|