Middleware lwIP on RAFW MCUs.
lwIP (Lightweight IP) is a widely used open-source TCP/IP stack designed for embedded systems with limited resources. Developed by Adam Dunkels at the Swedish Institute of Computer Science, lwIP is particularly suited for systems that need networking capabilities but have constraints on memory, processing power, and storage
The following build time configurations are defined in fsp_cfg/rm_lwip_w_cfg.h:
This module has no required clock configurations.
This module does not use I/O pins.
This is a basic example of minimal use of lwIP which attaches an interface and send packets to interface and recieve in the egress handler.
#if defined(__SUPPORT_IPV4__) && !defined(__SUPPORT_IPV6__)
#include "lwip/udp.h"
#include "lwip/etharp.h"
#include "lwip/inet.h"
#include "netif/ethernet.h"
#include "lwip/stats.h"
#include "lwip/prot/iana.h"
#include "lwip/tcpip.h"
#include "lwip/ip4_addr.h"
#include "lwip/apps/ping.h"
#include "portmacro.h"
#define DUMMY_MAC_ADDRESS {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
struct netif test_netif;
struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}};
static ip4_addr_t test_ipaddr, test_ipaddr1, test_netmask, test_gw;
const uint8_t mac_addr[6] = DUMMY_MAC_ADDRESS;
static int linkoutput_ctr;
const u8_t arp_reply[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x11, 0x22, 0x33,
0x44, 0x55, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
0x00, 0x02, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xc0, 0xa8,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0xc0, 0xa8,
0x00, 0x0a
};
static err_t
default_netif_linkoutput(struct netif *netif, struct pbuf *p)
{
size_t i = 0;
struct eth_hdr *ethhdr;
struct etharp_hdr *arphdr;
ip4_addr_t sipaddr, dipaddr;
TEST_ASSERT_EQUAL_PTR(&test_netif, netif);
TEST_ASSERT_NOT_NULL_MESSAGE(p, "PBUF is NULL");
linkoutput_ctr++;
if (p->len >= (sizeof(struct eth_hdr) + sizeof(struct etharp_hdr))) {
ethhdr = (struct eth_hdr *)p->payload;
if (htons(ethhdr->type) == ETHTYPE_ARP) {
arphdr = (struct etharp_hdr *)(p->payload + sizeof(struct eth_hdr));
uint16_t opcode = htons(arphdr->opcode);
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &arphdr->sipaddr);
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &arphdr->dipaddr);
if (opcode == ARP_REPLY) {
if (ip4_addr_cmp(&sipaddr, &dipaddr))
LWIP_DEBUG_PRINTF("\nDiscard gratuitous ARP announcement pkts opcode : %d\n", opcode);
else {
LWIP_DEBUG_PRINTF("\n===pbuf payload (ARP REPLY) recieved from lwIP===");
for (i = 0; i < p->len; i++) {
if(i % 16 == 0)
LWIP_DEBUG_PRINTF("\n");
LWIP_DEBUG_PRINTF("%02X ", ((unsigned char *)p->payload)[i]);
}
LWIP_DEBUG_PRINTF("\n");
if (memcmp(p->payload, &arp_reply, sizeof(arp_reply)) == 0) {
LWIP_DEBUG_PRINTF("\nVerification passed , ARP REPLY matches expected o/p\n");
return 1;
}
}
} else {
if (ip4_addr_cmp(&sipaddr, &dipaddr))
LWIP_DEBUG_PRINTF("\nDiscard gratuitous ARP announcement pkts opcode :%d\n", opcode);
}
} else {
LWIP_DEBUG_PRINTF("\nNot and ARP frame failed");
TEST_ASSERT(false);
}
} else {
LWIP_DEBUG_PRINTF("\nNot and Ethernet frame failed");
TEST_ASSERT(false);
}
return ERR_OK;
}
static err_t
default_netif_init(struct netif *netif)
{
netif->linkoutput = default_netif_linkoutput;
netif->output = etharp_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
return ERR_OK;
}
static void setup_interface(void)
{
static bool initialized = false;
if (!initialized)
{
initialized = true;
ip_addr_set_zero(&test_gw);
ip_addr_set_zero(&test_ipaddr);
ip_addr_set_zero(&test_netmask);
mem_init();
memp_init();
tcpip_init(NULL, NULL);
IP4_ADDR(&test_gw, 192,168,0,1);
IP4_ADDR(&test_ipaddr, 192,168,0,1);
IP4_ADDR(&test_netmask, 255,255,0,0);
memcpy(&test_netif.hwaddr, mac_addr, ETH_HWADDR_LEN);
if (netif_add(&test_netif,
&test_ipaddr, &test_netmask, &test_gw,
NULL,
default_netif_init,
ethernet_input) == NULL) {
TEST_ASSERT(false);
}
}
netif_set_default(&test_netif);
netif_set_up(&test_netif);
}
static void close_interface(void)
{
netif_remove(&test_netif);
}
static void create_send_ingress_pkt(void)
{
int k;
size_t i = 0;
struct eth_hdr *ethhdr;
struct etharp_hdr *etharphdr;
struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM);
if(p == NULL) {
TEST_ASSERT(false);
}
ethhdr = (struct eth_hdr*)p->payload;
etharphdr = (struct etharp_hdr*)(ethhdr + 1);
ethhdr->dest.addr[0] = 0xFF;
ethhdr->dest.addr[1] = 0xFF;
ethhdr->dest.addr[2] = 0xFF;
ethhdr->dest.addr[3] = 0xFF;
ethhdr->dest.addr[4] = 0xFF;
ethhdr->dest.addr[5] = 0xFF;
ethhdr->src = test_ethaddr2;
ethhdr->type = htons(ETHTYPE_ARP);
etharphdr->hwtype = htons(LWIP_IANA_HWTYPE_ETHERNET);
etharphdr->proto = htons(ETHTYPE_IP);
etharphdr->hwlen = ETHARP_HWADDR_LEN;
etharphdr->protolen = sizeof(ip4_addr_t);
etharphdr->opcode = htons(ARP_REQUEST);
IP4_ADDR(&test_ipaddr1, 192,168,0,10);
SMEMCPY(ðarphdr->sipaddr, &test_ipaddr1, sizeof(ip4_addr_t));
SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t));
k = 6;
while(k > 0) {
k--;
etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k];
etharphdr->dhwaddr.addr[k] = 0x00;
ethhdr->dest.addr[k] = 0xFF;
ethhdr->src.addr[k] = test_ethaddr2.addr[k];
}
LWIP_DEBUG_PRINTF("\n=====payload sent to lwIP(ARP REQ)==== ");
for (i = 0; i < p->len; i++) {
if(i % 16 == 0)
LWIP_DEBUG_PRINTF("\n");
LWIP_DEBUG_PRINTF("%02X ", ((unsigned char *)p->payload)[i]);
}
LWIP_DEBUG_PRINTF("\n");
if(test_netif.input(p, &test_netif) != ERR_OK)
{
pbuf_free(p);
}
}
void lwip_main(void)
{
setup_interface();
create_send_ingress_pkt();
close_interface();
}
#endif