chenyong 7 лет назад
Родитель
Сommit
062c86edd9
3 измененных файлов с 316 добавлено и 7 удалено
  1. 12 2
      README.md
  2. 286 0
      src/wiz_ping.c
  3. 18 5
      src/wiz_socket.c

+ 12 - 2
README.md

@@ -102,7 +102,7 @@ int wiz_init(void);
 int wiz_set_mac(const char *mac);
 ```
 
-设备上电初始化完成,设置设备 MAC 地址成功,然后可以在 FinSH 中输入命令 `wiz_ifconfig` 查看网络连接状态,如下图所示:
+设备上电初始化完成,设置设备 MAC 地址成功,然后可以在 FinSH 中输入命令 `wiz_ifconfig` 查看设备 IP 地址、MAC 地址等网络信息,如下所示:
 
 ```shell
 msh />wiz_ifconfig
@@ -115,7 +115,17 @@ net mask  : 255.255.0.0         ## 设备子网掩码
 dns server : 192.168.10.1       ## 域名解析服务器地址
 ```
 
-网络连接成功,可以使用 SAL 抽象出来的标准 BSD Socket APIs 进行网络开发(MQTT、HTTP、mbedtls、ntp、
+获取 IP 地址成功之后,可以在 FinSH 中输入命令 `wiz_ping + 域名地址` 测试网络连接状态, 如下所示:
+
+```shell
+msh />wiz_ping baidu.com
+32 bytes from 220.181.57.216 icmp_seq=0 ttl=128 time=31 ticks
+32 bytes from 220.181.57.216 icmp_seq=1 ttl=128 time=31 ticks
+32 bytes from 220.181.57.216 icmp_seq=2 ttl=128 time=32 ticks
+32 bytes from 220.181.57.216 icmp_seq=3 ttl=128 time=32 ticks
+```
+
+`wiz_ping` 命令测试正常说明 WIZnet 设备网络连接成功,之后可以使用 SAL(套接字抽象层) 抽象出来的标准 BSD Socket APIs 进行网络开发(MQTT、HTTP、mbedtls、ntp、
 
  iperf 等),WIZnet 软件包支持的协议簇类型为:主协议簇 **AF_WIZ**、次协议簇 **AF_INET**(具体区别和使用方式可查看  [SAL 编程指南](https://www.rt-thread.org/document/site/submodules/rtthread-manual-doc/zh/1chapters/13-chapter_sal/))。
 

+ 286 - 0
src/wiz_ping.c

@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-09-26     chenyong     first version
+ */
+
+#include <stdlib.h>
+#include <rtthread.h>
+
+#include <W5500/w5500.h>
+#include <wiz_socket.h>
+
+#define Sn_PROTO(ch)         (0x001408 + (ch<<5))
+
+#define WIZ_PING_DATA_LEN    32
+#define WIZ_PING_HEAD_LEN    8
+
+#define WIZ_PING_PORT        3000
+#define WIZ_PING_REQUEST     8
+#define WIZ_PING_REPLY       0
+#define WIZ_PING_CODE        0
+#define WIZ_PING_DELAY      (1 * RT_TICK_PER_SECOND)
+#define WIZ_PING_TIMEOUT    (2 * RT_TICK_PER_SECOND)
+
+struct wiz_ping_msg
+{
+    uint8_t   type;                    // 0 - Ping Reply, 8 - Ping Request
+    uint8_t   code;                    // Always 0
+    uint16_t  check_sum;               // Check sum
+    uint16_t  id;                      // Identification
+    uint16_t  seq_num;                 // Sequence Number
+    int8_t    data[WIZ_PING_DATA_LEN]; // Ping Data  : 1452 = IP RAW MTU - sizeof(type+code+check_sum+id+seq_num)
+};
+
+/* calculate string check value */
+static uint16_t wiz_checksum( uint8_t *src, uint32_t len )
+{
+    uint16_t sum, tsum, i, j;
+    uint32_t lsum;
+
+    j = len >> 1;
+    lsum = 0;
+
+    for (i = 0; i < j; i++)
+    {
+        tsum = src[i * 2];
+        tsum = tsum << 8;
+        tsum += src[i * 2 + 1];
+        lsum += tsum;
+    }
+
+    if (len % 2)
+    {
+        tsum = src[i * 2];
+        lsum += (tsum << 8);
+    }
+
+    sum = lsum;
+    sum = ~(sum + (lsum >> 16));
+    return (uint16_t) sum;
+}
+
+static int wiz_ping_request(int socket)
+{
+    int idx, send_len;
+    uint16_t tmp_checksum;
+    struct wiz_ping_msg ping_req;
+
+    /* set request ping message object */
+    ping_req.type = WIZ_PING_REQUEST;
+    ping_req.code = WIZ_PING_CODE;
+    ping_req.id = htons(rand() % 0xffff);
+    ping_req.seq_num = htons(rand() % 0xffff);
+    for (idx = 0; idx < WIZ_PING_DATA_LEN; idx++)
+    {
+        ping_req.data[idx] = (idx) % 8;
+    }
+    ping_req.check_sum = 0;
+    /* calculate request ping message check value */
+    tmp_checksum = wiz_checksum((uint8_t *) &ping_req, sizeof(ping_req));
+    ping_req.check_sum = htons(tmp_checksum);
+
+    /* send request ping message */
+    send_len = wiz_send(socket, &ping_req, sizeof(ping_req), 0);
+    if (send_len != sizeof(ping_req))
+    {
+        return -1;
+    }
+
+    return send_len - WIZ_PING_HEAD_LEN;
+}
+
+static int wiz_ping_reply(int socket)
+{
+    uint16_t tmp_checksum;
+    uint8_t recv_buf[WIZ_PING_HEAD_LEN + WIZ_PING_DATA_LEN + 1];
+    struct wiz_ping_msg ping_rep;
+    rt_tick_t start_tick;
+    int recv_len;
+    int idx;
+
+    start_tick = rt_tick_get();
+    while(1)
+    {
+        if (rt_tick_get() - start_tick > WIZ_PING_TIMEOUT)
+        {
+            return -1;
+        }
+
+        if (getSn_RX_RSR(socket) <= 0)
+        {
+            rt_thread_mdelay(1);
+            continue;
+        }
+        else
+        {
+            recv_len = wiz_recv(socket, recv_buf, WIZ_PING_HEAD_LEN + WIZ_PING_DATA_LEN, 0);
+            if (recv_len < 0)
+            {
+                return -1;
+            }
+            break;
+        }
+    }
+
+    if (recv_buf[0] == WIZ_PING_REPLY)
+    {
+        ping_rep.type        = recv_buf[0];
+        ping_rep.code        = recv_buf[1];
+        ping_rep.check_sum   = (recv_buf[3] << 8) + recv_buf[2];
+        ping_rep.id          = (recv_buf[5] << 8) + recv_buf[4];
+        ping_rep.seq_num     = (recv_buf[7] << 8) + recv_buf[6];
+        for (idx = 0; idx < recv_len - 8; idx++)
+        {
+            ping_rep.data[idx] = recv_buf[8 + idx];
+        }
+
+        tmp_checksum = ~wiz_checksum(recv_buf, recv_len);
+        if (tmp_checksum != 0xffff)
+        {
+            return -2;
+        }
+    }
+    else if (recv_buf[0] == WIZ_PING_REQUEST)
+    {
+        ping_rep.code        = recv_buf[1];
+        ping_rep.type        = recv_buf[2];
+        ping_rep.check_sum   = (recv_buf[3] << 8) + recv_buf[2];
+        ping_rep.id          = (recv_buf[5] << 8) + recv_buf[4];
+        ping_rep.seq_num     = (recv_buf[7] << 8) + recv_buf[6];
+        for (idx = 0; idx < recv_len - 8; idx++)
+        {
+            ping_rep.data[idx] = recv_buf[8 + idx];
+        }
+
+        tmp_checksum = ping_rep.check_sum;
+        ping_rep.check_sum = 0;
+        if (tmp_checksum != ping_rep.check_sum)
+        {
+            return -2;
+        }
+    }
+    else
+    {
+        rt_kprintf("wiz_ping: unknown ping receive message.\n");
+        return -1;
+    }
+
+    return recv_len - WIZ_PING_HEAD_LEN;
+}
+
+int wiz_ping(char* target_name, uint32_t times)
+{
+    int result, socket;
+    uint32_t send_times;
+    struct hostent *host;
+    struct sockaddr_in server_addr;
+    struct timeval timeout;
+    struct in_addr ina;
+
+    socket = -1;
+    send_times = 0;
+
+    /* domain name resolution */
+    host = wiz_gethostbyname(target_name);
+    if (host == RT_NULL)
+    {
+        rt_kprintf("wiz_ping: unknown host %s\n", target_name);
+        return -1;
+    }
+
+    socket = wiz_socket(AF_WIZ, SOCK_RAW, 0);
+    if (socket < 0)
+    {
+        rt_kprintf("wiz_ping: create ping socket(%d) failed.\n");
+        return -1;
+    }
+    /* set socket ICMP protocol */
+    IINCHIP_WRITE(Sn_PROTO(socket), IPPROTO_ICMP);
+
+    /* Check socket register */
+    while(getSn_SR(socket) != SOCK_IPRAW);
+
+    timeout.tv_sec = WIZ_PING_TIMEOUT;
+    timeout.tv_usec = 0;
+
+    /* set receive and send timeout option */
+    wiz_setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout,
+               sizeof(timeout));
+    wiz_setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (void *) &timeout,
+               sizeof(timeout));
+
+    server_addr.sin_family = AF_WIZ;
+    server_addr.sin_port = htons(WIZ_PING_PORT);
+    server_addr.sin_addr = *((struct in_addr *) host->h_addr);
+    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
+    rt_memcpy(&ina, &server_addr.sin_addr, sizeof(ina));
+
+    if (wiz_connect(socket, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) < 0)
+    {
+        wiz_closesocket(socket);
+        return -1;
+    }
+
+    while (1)
+    {
+        if ((result = wiz_ping_request(socket)) > 0)
+        {
+            rt_tick_t recv_start_tick;
+
+            recv_start_tick = rt_tick_get();
+            if ((result = wiz_ping_reply(socket)) >= 0)
+            {
+                rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ticks\n", result, inet_ntoa(ina), send_times,
+                        getSn_TTL(socket), rt_tick_get() - recv_start_tick);
+            }
+            else
+            {
+                rt_kprintf("wiz_ping: receive data from %s failed(%d).\n", inet_ntoa(ina), result);
+            }
+
+            rt_thread_mdelay(100);
+        }
+        else
+        {
+            rt_kprintf("wiz_ping: send data to %s failed(%d).\n", inet_ntoa(ina), result);
+        }
+
+        send_times++;
+        if (send_times >= times)
+        {
+            /* send ping times reached, stop */
+            break;
+        }
+
+        rt_thread_mdelay(WIZ_PING_DELAY); /* take a delay */
+    }
+
+    wiz_closesocket(socket);
+
+    return 0;
+}
+
+
+int cmd_wiz_ping(int argc, char **argv)
+{
+    if (argc == 1)
+    {
+        rt_kprintf("Please input: wiz_ping <host address>\n");
+        return -1;
+    }
+    else
+    {
+        wiz_ping(argv[1], 4);
+    }
+
+    return 0;
+}
+
+#ifdef FINSH_USING_MSH
+MSH_CMD_EXPORT_ALIAS(cmd_wiz_ping, wiz_ping, WIZnet ping network host);
+#endif

+ 18 - 5
src/wiz_socket.c

@@ -294,6 +294,10 @@ int wiz_socket(int domain, int type, int protocol)
         socket_type = Sn_MR_UDP;
         break;
 
+    case SOCK_RAW:
+        socket_type = Sn_MR_IPRAW;
+        break;
+
     default:
         LOG_E("don't support socket type (%d)!", type);
         return -1;
@@ -327,6 +331,7 @@ int wiz_socket(int domain, int type, int protocol)
             break;
 
         case Sn_MR_UDP:
+        case Sn_MR_IPRAW:
             if (wizchip_socket(sock->socket, sock->type, wiz_port++, 0) != sock->socket)
             {
                 LOG_E("WIZnet UDP socket(%d) create failed!", sock->socket);
@@ -474,7 +479,7 @@ int wiz_connect(int socket, const struct sockaddr *name, socklen_t namelen)
     }
 
     socket_state = getSn_SR(socket);
-    if (socket_state == SOCK_UDP)
+    if (socket_state == SOCK_UDP || socket_state == SOCK_IPRAW)
     {
         if(sock->server_addr == RT_NULL)
         {
@@ -566,13 +571,15 @@ int wiz_sendto(int socket, const void *data, size_t size, int flags, const struc
         }
         break;
     }
+
     case Sn_MR_UDP:
+    case Sn_MR_IPRAW:
     {
         ip_addr_t remote_addr;
         uint16_t remote_port = 0;
         uint8_t ipstr[4] = { 0 };
 
-        if (socket_state != SOCK_UDP)
+        if (socket_state != SOCK_UDP && socket_state != SOCK_IPRAW)
         {
             LOG_E("WIZnet sendto failed, get socket(%d) register state(%d) error.", socket, socket_state);
             return -1;
@@ -690,13 +697,14 @@ int wiz_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *
     }
 
     case Sn_MR_UDP:
+    case Sn_MR_IPRAW:
     {
         ip_addr_t remote_addr;
         uint16_t remote_port = 0;
         uint8_t ipstr[4] = { 0 };
         uint16_t rx_len = 0;
 
-        if (socket_state != SOCK_UDP)
+        if (socket_state != SOCK_UDP && socket_state != SOCK_IPRAW)
         {
             LOG_E("WIZnet recvfrom failed, get socket(%d) register state(%d) error.", socket, socket_state);
             return -1;
@@ -973,7 +981,7 @@ struct hostent *wiz_gethostbyname(const char *name)
         for (idx = 0; idx < WIZ_SOCKETS_NUM && sockets[idx].magic; idx++);
         if (idx >= WIZ_SOCKETS_NUM)
         {
-            LOG_E("wizenet DNS failed, socket number is full.");
+            LOG_E("WIZnet DNS failed, socket number is full.");
             return RT_NULL;
         }
 
@@ -988,7 +996,12 @@ struct hostent *wiz_gethostbyname(const char *name)
         }
         else if (ret < 0)
         {
-            LOG_E("WIZnet gethostbyname failed(%d).", ret);
+            return RT_NULL;
+        }
+
+        /* domain resolve failed */
+        if (remote_ip[0] == 0)
+        {
             return RT_NULL;
         }