Files
CCU621M/BSP/net_lwip/netconf.c
T

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, &ethernetif_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, &ethernetif_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 */