1 /* 2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 3 * COPYRIGHT (C) 2006-2010, RT-Thread Development Team 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 26 * OF SUCH DAMAGE. 27 * 28 * This file is part of the lwIP TCP/IP stack. 29 * 30 * Author: Adam Dunkels <[email protected]> 31 * 32 * Change Logs: 33 * Date Author Notes 34 * 2010-07-07 Bernard fix send mail to mailbox issue. 35 * 2011-07-30 mbbill port lwIP 1.4.0 to RT-Thread 36 * 2012-04-10 Bernard add more compatible with RT-Thread. 37 * 2012-11-12 Bernard The network interface can be initialized 38 * after lwIP initialization. 39 * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. 40 */ 41 42 #include <rtthread.h> 43 44 #include "lwip/opt.h" 45 #include "lwip/debug.h" 46 #include "lwip/def.h" 47 #include "lwip/mem.h" 48 #include "lwip/pbuf.h" 49 #include "lwip/sys.h" 50 #include "lwip/netif.h" 51 #include "lwip/stats.h" 52 #include "lwip/tcpip.h" 53 54 #include "netif/etharp.h" 55 #include "netif/ethernetif.h" 56 #include "lwip/inet.h" 57 58 #define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) 59 #define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) 60 61 #ifndef RT_LWIP_ETHTHREAD_PRIORITY 62 #define RT_ETHERNETIF_THREAD_PREORITY 0x90 63 #else 64 #define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY 65 #endif 66 67 #ifndef LWIP_NO_TX_THREAD 68 /** 69 * Tx message structure for Ethernet interface 70 */ 71 struct eth_tx_msg 72 { 73 struct netif *netif; 74 struct pbuf *buf; 75 }; 76 77 static struct rt_mailbox eth_tx_thread_mb; 78 static struct rt_thread eth_tx_thread; 79 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE 80 static char eth_tx_thread_mb_pool[32 * 4]; 81 static char eth_tx_thread_stack[512]; 82 #else 83 static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; 84 static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; 85 #endif 86 #endif 87 88 #ifndef LWIP_NO_RX_THREAD 89 static struct rt_mailbox eth_rx_thread_mb; 90 static struct rt_thread eth_rx_thread; 91 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE 92 static char eth_rx_thread_mb_pool[48 * 4]; 93 static char eth_rx_thread_stack[1024]; 94 #else 95 static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; 96 static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; 97 #endif 98 #endif 99 100 static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) 101 { 102 #ifndef LWIP_NO_TX_THREAD 103 struct eth_tx_msg msg; 104 struct eth_device* enetif; 105 106 RT_ASSERT(netif != RT_NULL); 107 enetif = (struct eth_device*)netif->state; 108 109 /* send a message to eth tx thread */ 110 msg.netif = netif; 111 msg.buf = p; 112 if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK) 113 { 114 /* waiting for ack */ 115 rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); 116 } 117 #else 118 struct eth_device* enetif; 119 120 RT_ASSERT(netif != RT_NULL); 121 enetif = (struct eth_device*)netif->state; 122 123 if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK) 124 { 125 return ERR_IF; 126 } 127 #endif 128 return ERR_OK; 129 } 130 131 static err_t eth_netif_device_init(struct netif *netif) 132 { 133 struct eth_device *ethif; 134 135 ethif = (struct eth_device*)netif->state; 136 if (ethif != RT_NULL) 137 { 138 rt_device_t device; 139 140 /* get device object */ 141 device = (rt_device_t) ethif; 142 if (rt_device_init(device) != RT_EOK) 143 { 144 return ERR_IF; 145 } 146 147 /* copy device flags to netif flags */ 148 netif->flags = (ethif->flags & 0xff); 149 150 /* set default netif */ 151 if (netif_default == RT_NULL) 152 netif_set_default(ethif->netif); 153 154 #if LWIP_DHCP 155 if (ethif->flags & NETIF_FLAG_DHCP) 156 { 157 /* if this interface uses DHCP, start the DHCP client */ 158 dhcp_start(ethif->netif); 159 } 160 else 161 #endif 162 { 163 /* set interface up */ 164 netif_set_up(ethif->netif); 165 } 166 167 if (!(ethif->flags & ETHIF_LINK_PHYUP)) 168 { 169 /* set link_up for this netif */ 170 netif_set_link_up(ethif->netif); 171 } 172 173 return ERR_OK; 174 } 175 176 return ERR_IF; 177 } 178 179 /* Keep old drivers compatible in RT-Thread */ 180 rt_err_t eth_device_init_with_flag(struct eth_device *dev, char *name, rt_uint16_t flags) 181 { 182 struct netif* netif; 183 184 netif = (struct netif*) rt_malloc (sizeof(struct netif)); 185 if (netif == RT_NULL) 186 { 187 rt_kprintf("malloc netif failed\n"); 188 return -RT_ERROR; 189 } 190 rt_memset(netif, 0, sizeof(struct netif)); 191 192 /* set netif */ 193 dev->netif = netif; 194 /* device flags, which will be set to netif flags when initializing */ 195 dev->flags = flags; 196 /* link changed status of device */ 197 dev->link_changed = 0x00; 198 dev->parent.type = RT_Device_Class_NetIf; 199 /* register to RT-Thread device manager */ 200 rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR); 201 rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO); 202 203 /* set name */ 204 netif->name[0] = name[0]; 205 netif->name[1] = name[1]; 206 207 /* set hw address to 6 */ 208 netif->hwaddr_len = 6; 209 /* maximum transfer unit */ 210 netif->mtu = ETHERNET_MTU; 211 212 /* get hardware MAC address */ 213 rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr); 214 215 /* set output */ 216 netif->output = etharp_output; 217 netif->linkoutput = ethernetif_linkoutput; 218 219 /* if tcp thread has been started up, we add this netif to the system */ 220 if (rt_thread_find("tcpip") != RT_NULL) 221 { 222 struct ip_addr ipaddr, netmask, gw; 223 224 #if LWIP_DHCP 225 if (dev->flags & NETIF_FLAG_DHCP) 226 { 227 IP4_ADDR(&ipaddr, 0, 0, 0, 0); 228 IP4_ADDR(&gw, 0, 0, 0, 0); 229 IP4_ADDR(&netmask, 0, 0, 0, 0); 230 } 231 else 232 #endif 233 { 234 ipaddr.addr = inet_addr(RT_LWIP_IPADDR); 235 gw.addr = inet_addr(RT_LWIP_GWADDR); 236 netmask.addr = inet_addr(RT_LWIP_MSKADDR); 237 } 238 239 netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input); 240 } 241 242 return RT_EOK; 243 } 244 245 rt_err_t eth_device_init(struct eth_device * dev, char *name) 246 { 247 rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; 248 249 #if LWIP_DHCP 250 /* DHCP support */ 251 flags |= NETIF_FLAG_DHCP; 252 #endif 253 254 #if LWIP_IGMP 255 /* IGMP support */ 256 flags |= NETIF_FLAG_IGMP; 257 #endif 258 259 return eth_device_init_with_flag(dev, name, flags); 260 } 261 262 #ifndef LWIP_NO_RX_THREAD 263 rt_err_t eth_device_ready(struct eth_device* dev) 264 { 265 if (dev->netif) 266 /* post message to Ethernet thread */ 267 return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); 268 else 269 return ERR_OK; /* netif is not initialized yet, just return. */ 270 } 271 272 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) 273 { 274 rt_uint32_t level; 275 276 RT_ASSERT(dev != RT_NULL); 277 278 level = rt_hw_interrupt_disable(); 279 dev->link_changed = 0x01; 280 if (up == RT_TRUE) 281 dev->link_status = 0x01; 282 else 283 dev->link_status = 0x00; 284 rt_hw_interrupt_enable(level); 285 286 /* post message to ethernet thread */ 287 return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); 288 } 289 #else 290 /* NOTE: please not use it in interrupt when no RxThread exist */ 291 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) 292 { 293 if (up == RT_TRUE) 294 netifapi_netif_set_link_up(dev->netif); 295 else 296 netifapi_netif_set_link_down(dev->netif); 297 298 return RT_EOK; 299 } 300 #endif 301 302 #ifndef LWIP_NO_TX_THREAD 303 /* Ethernet Tx Thread */ 304 static void eth_tx_thread_entry(void* parameter) 305 { 306 struct eth_tx_msg* msg; 307 308 while (1) 309 { 310 if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t*)&msg, RT_WAITING_FOREVER) == RT_EOK) 311 { 312 struct eth_device* enetif; 313 314 RT_ASSERT(msg->netif != RT_NULL); 315 RT_ASSERT(msg->buf != RT_NULL); 316 317 enetif = (struct eth_device*)msg->netif->state; 318 if (enetif != RT_NULL) 319 { 320 /* call driver's interface */ 321 if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK) 322 { 323 /* transmit eth packet failed */ 324 } 325 } 326 327 /* send ACK */ 328 rt_sem_release(&(enetif->tx_ack)); 329 } 330 } 331 } 332 #endif 333 334 #ifndef LWIP_NO_RX_THREAD 335 /* Ethernet Rx Thread */ 336 static void eth_rx_thread_entry(void* parameter) 337 { 338 struct eth_device* device; 339 340 while (1) 341 { 342 if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t*)&device, RT_WAITING_FOREVER) == RT_EOK) 343 { 344 struct pbuf *p; 345 346 /* check link status */ 347 if (device->link_changed) 348 { 349 int status; 350 rt_uint32_t level; 351 352 level = rt_hw_interrupt_disable(); 353 status = device->link_status; 354 device->link_changed = 0x00; 355 rt_hw_interrupt_enable(level); 356 357 if (status) 358 netifapi_netif_set_link_up(device->netif); 359 else 360 netifapi_netif_set_link_down(device->netif); 361 } 362 363 /* receive all of buffer */ 364 while (1) 365 { 366 if(device->eth_rx == RT_NULL) break; 367 368 p = device->eth_rx(&(device->parent)); 369 if (p != RT_NULL) 370 { 371 /* notify to upper layer */ 372 if( device->netif->input(p, device->netif) != ERR_OK ) 373 { 374 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); 375 pbuf_free(p); 376 p = NULL; 377 } 378 } 379 else break; 380 } 381 } 382 else 383 { 384 LWIP_ASSERT("Should not happen!\n",0); 385 } 386 } 387 } 388 #endif 389 390 int eth_system_device_init(void) 391 { 392 rt_err_t result = RT_EOK; 393 394 /* initialize Rx thread. */ 395 #ifndef LWIP_NO_RX_THREAD 396 /* initialize mailbox and create Ethernet Rx thread */ 397 result = rt_mb_init(ð_rx_thread_mb, "erxmb", 398 ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4, 399 RT_IPC_FLAG_FIFO); 400 RT_ASSERT(result == RT_EOK); 401 402 result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL, 403 ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack), 404 RT_ETHERNETIF_THREAD_PREORITY, 16); 405 RT_ASSERT(result == RT_EOK); 406 result = rt_thread_startup(ð_rx_thread); 407 RT_ASSERT(result == RT_EOK); 408 #endif 409 410 /* initialize Tx thread */ 411 #ifndef LWIP_NO_TX_THREAD 412 /* initialize mailbox and create Ethernet Tx thread */ 413 result = rt_mb_init(ð_tx_thread_mb, "etxmb", 414 ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4, 415 RT_IPC_FLAG_FIFO); 416 RT_ASSERT(result == RT_EOK); 417 418 result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL, 419 ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack), 420 RT_ETHERNETIF_THREAD_PREORITY, 16); 421 RT_ASSERT(result == RT_EOK); 422 423 result = rt_thread_startup(ð_tx_thread); 424 RT_ASSERT(result == RT_EOK); 425 #endif 426 427 return (int)result; 428 } 429 INIT_PREV_EXPORT(eth_system_device_init); 430 431 #ifdef RT_USING_FINSH 432 #include <finsh.h> 433 void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) 434 { 435 struct ip_addr *ip; 436 struct ip_addr addr; 437 struct netif * netif = netif_list; 438 439 if(strlen(netif_name) > sizeof(netif->name)) 440 { 441 rt_kprintf("network interface name too long!\r\n"); 442 return; 443 } 444 445 while(netif != RT_NULL) 446 { 447 if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) 448 break; 449 450 netif = netif->next; 451 if( netif == RT_NULL ) 452 { 453 rt_kprintf("network interface: %s not found!\r\n", netif_name); 454 return; 455 } 456 } 457 458 ip = (struct ip_addr *)&addr; 459 460 /* set ip address */ 461 if ((ip_addr != RT_NULL) && ipaddr_aton(ip_addr, &addr)) 462 { 463 netif_set_ipaddr(netif, ip); 464 } 465 466 /* set gateway address */ 467 if ((gw_addr != RT_NULL) && ipaddr_aton(gw_addr, &addr)) 468 { 469 netif_set_gw(netif, ip); 470 } 471 472 /* set netmask address */ 473 if ((nm_addr != RT_NULL) && ipaddr_aton(nm_addr, &addr)) 474 { 475 netif_set_netmask(netif, ip); 476 } 477 } 478 FINSH_FUNCTION_EXPORT(set_if, set network interface address); 479 480 #if LWIP_DNS 481 #include <lwip/dns.h> 482 void set_dns(char* dns_server) 483 { 484 struct ip_addr addr; 485 486 if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr)) 487 { 488 dns_setserver(0, &addr); 489 } 490 } 491 FINSH_FUNCTION_EXPORT(set_dns, set DNS server address); 492 #endif 493 494 void list_if(void) 495 { 496 rt_ubase_t index; 497 struct netif * netif; 498 499 rt_enter_critical(); 500 501 netif = netif_list; 502 503 while( netif != RT_NULL ) 504 { 505 rt_kprintf("network interface: %c%c%s\n", 506 netif->name[0], 507 netif->name[1], 508 (netif == netif_default)?" (Default)":""); 509 rt_kprintf("MTU: %d\n", netif->mtu); 510 rt_kprintf("MAC: "); 511 for (index = 0; index < netif->hwaddr_len; index ++) 512 rt_kprintf("%02x ", netif->hwaddr[index]); 513 rt_kprintf("\nFLAGS:"); 514 if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP"); 515 else rt_kprintf(" DOWN"); 516 if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP"); 517 else rt_kprintf(" LINK_DOWN"); 518 if (netif->flags & NETIF_FLAG_DHCP) rt_kprintf(" DHCP"); 519 if (netif->flags & NETIF_FLAG_POINTTOPOINT) rt_kprintf(" PPP"); 520 if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP"); 521 if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP"); 522 rt_kprintf("\n"); 523 rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr))); 524 rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw))); 525 rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask))); 526 rt_kprintf("\r\n"); 527 528 netif = netif->next; 529 } 530 531 #if LWIP_DNS 532 { 533 struct ip_addr ip_addr; 534 535 for(index=0; index<DNS_MAX_SERVERS; index++) 536 { 537 ip_addr = dns_getserver(index); 538 rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(&(ip_addr))); 539 } 540 } 541 #endif /**< #if LWIP_DNS */ 542 543 rt_exit_critical(); 544 } 545 FINSH_FUNCTION_EXPORT(list_if, list network interface information); 546 547 #if LWIP_TCP 548 #include <lwip/tcp.h> 549 #include <lwip/tcp_impl.h> 550 551 void list_tcps(void) 552 { 553 rt_uint32_t num = 0; 554 struct tcp_pcb *pcb; 555 char local_ip_str[16]; 556 char remote_ip_str[16]; 557 558 extern struct tcp_pcb *tcp_active_pcbs; 559 extern union tcp_listen_pcbs_t tcp_listen_pcbs; 560 extern struct tcp_pcb *tcp_tw_pcbs; 561 extern const char *tcp_state_str[]; 562 563 rt_enter_critical(); 564 rt_kprintf("Active PCB states:\n"); 565 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) 566 { 567 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 568 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 569 570 rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", 571 num++, 572 local_ip_str, 573 pcb->local_port, 574 remote_ip_str, 575 pcb->remote_port, 576 pcb->snd_nxt, 577 pcb->rcv_nxt); 578 rt_kprintf("state: %s\n", tcp_state_str[pcb->state]); 579 } 580 581 rt_kprintf("Listen PCB states:\n"); 582 num = 0; 583 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) 584 { 585 rt_kprintf("#%d local port %d ", num++, pcb->local_port); 586 rt_kprintf("state: %s\n", tcp_state_str[pcb->state]); 587 } 588 589 rt_kprintf("TIME-WAIT PCB states:\n"); 590 num = 0; 591 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) 592 { 593 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 594 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 595 596 rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", 597 num++, 598 local_ip_str, 599 pcb->local_port, 600 remote_ip_str, 601 pcb->remote_port, 602 pcb->snd_nxt, 603 pcb->rcv_nxt); 604 rt_kprintf("state: %s\n", tcp_state_str[pcb->state]); 605 } 606 rt_exit_critical(); 607 } 608 FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections); 609 #endif 610 611 #if LWIP_UDP 612 #include "lwip/udp.h" 613 void list_udps(void) 614 { 615 struct udp_pcb *pcb; 616 rt_uint32_t num = 0; 617 char local_ip_str[16]; 618 char remote_ip_str[16]; 619 620 rt_enter_critical(); 621 rt_kprintf("Active UDP PCB states:\n"); 622 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) 623 { 624 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 625 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 626 627 rt_kprintf("#%d %d %s:%d <==> %s:%d \n", 628 num, (int)pcb->flags, 629 local_ip_str, 630 pcb->local_port, 631 remote_ip_str, 632 pcb->remote_port); 633 634 num++; 635 } 636 rt_exit_critical(); 637 } 638 FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections); 639 #endif /* LWIP_UDP */ 640 641 #endif 642