Network performance of SoC with TCP/IP Offload engine, W7500

This post shows how to measure Network perfromance by using Iperf and how to configure W7500 to improve Network performance.

.

TOE allows to offload the processing of TCP/IP protocols from the host microcontroller,
In TCP/IP protocol stack

TOE

TOE performance according to AHB bus clock (w/o DMA, RX Buffer:8KB)

Network performance

Advertisements

WZTOE Coding Guide for WIZwiki-W7500

WIZwiki_W7500

wizwiki_W7500

  • WIZnet W7500
  • 32-bit ARM Cortex-M0
  • 128KB Flash / 48 SRAM
  • Hardware TCP/IP coe (WIZnet TCP/IP Engine)
  • 64TQFP( 7x7mm)

  • CMSIS-DAP

  • SWD Con.

  • WIZwiki-W7500 feature

  • Arduino Pin compatible

  • ISP / SD Slot / REG LED
  • Ethernet PHY

HW : MII Interface

MII Interface
* WZTOE Signals

W7500_WZTOE Ethernet PHY
PD_00 CRS
PD_01 RXDV
PD_02 RXD0
PD_03 RXD1
PD_04 RXD2
PD_06 RXD3
PB_04 TXEN
PB_05 COL
PB_07 RXCLK
PB_08 DUP
PB_09 TXCLK
PB_10 TXD0
PB_11 TXD1
PB_12 TXD2
PB_13 TXD3
  • MDIO via GPIO

    Management Data Input/Output (MDIO), also known as Serial Management Interface (SMI) or Media Independent Interface Management (MIIM), is a serial bus defined for the Ethernet family of IEEE 802.3 standards for the Media Independent Interface, or MII. The MII connects Media Access Control (MAC) devices with Ethernet physical layer (PHY) circuits.
    http://en.wikipedia.org/wiki/Management_Data_Input/Output

  • PB_14 — MDIO (@IC+101)

  • PB_15 — MDC (@IC+101

SW : (will update code location)

  • ioLibary :“Internet Offload Library” for WIZnet chip. It includes drivers and application protocols.
    $\W7500_FW\Projects\Peripheral_Examples\WZTOE\ioLibrary

  • MDIO via GPIO: It Includes the MDIO Read and Write functions.
    $\W7500_FW\Projects\Peripheral_Examples\WZTOE\ioLibrary\MDIO\W7500x_miim.h
    $\W7500_FW\Projects\Peripheral_Examples\WZTOE\ioLibrary\MDIO\W7500x_miim.c

  • W7500 WZTOE (WIZnet TCPIP Engine) Driver
    $\W7500_FW\Libraries\W7500x_stdPeriph_Driver\inc\W7500x_WZTOE.h
    $\W7500_FW\Libraries\W7500x_stdPeriph_Driver\src\W7500x_WZTOE.c

Coding Guides

  • To use accurate Ticker of 1usec, set WZ100US value according to main clock(HCLK)
/* Set WZ_100US Register */
setTIC100US((GetSystemClock()/10000));
//getTIC100US();
//printf(" GetSystemClock: %X, getTIC100US: %X, (%X) rn",
// GetSystemClock, getTIC100US(), *(uint32_t *)TIC100US);
  • To clear Interrupt register, use Interrupt Clear Register (ICR) , Socket Interrupt Clear Register(Sn_ICR).
setSn_IMR(socket_number, interrupt_mask_bits);
...
socket_interrupt_state = getSn_IR(socket_number);
...
socket_interrupt_state = setSn_ICR(socket_number, interrupt_clear_bit);
  • To use previous codes, setSn_ICR() is warped by setSn_IR().

  • How to access WZTOE
    Memory map of TOE memory

  • Registers

#define WZTOE_COMMON_REGISTER_BASEADDR (0x4100_0000)
#define WZTOE_SOCKET_REGISTER_BASEADDR(sock_num) (0x4101_0000 + (sock_num)<<18))

/* Write to wztoe common register with offset address of 3 */
offset_addr = 3;
*(volatile uint32_t *)(WZTOE_COMMON_REGISTER_BASEADDR + offset_addr) = 0x12;

/* Read to wztoe socket 3 register with offset address of 8 */
sock_num = 3;
offset_addr = 8;
val = *(volatile uint32_t *)(WZTOE_SOCKET_REGISTER_BASEADDR(sock_num) + offset_addr)
  • TX/RX Buffer
    Cortex-m0 is able to access by 32-bits address. However, Sn_TX_WR(Socket n TX Write Pointer Register) and Sn_RX_RD (Socket n RX Read Pointer Register) is only the lower 16 bits of the pointer. Hence, to calcurate the address boundary, offset address shoud be masked by 0xFFFF.
#define WZTOE_SOCKET_TXBUF_BASEADDR(sock_num) (0x4102_0000 + (sock_num)<<18))
#define WZTOE_SOCKET_RXBUF_BASEADDR(sock_num) (0x4103_0000 + (sock_num)<<18))

/* Write to wztoe TX buffer with offset address of 3 */
sock_num = 3;
offset_addr = 0x0001_0000;
*(volatile uint32_t *)(WZTOE_SOCKET_TXBUF_BASEADDR(sock_num) + (offset_addr&0xFFFF)) = 0x12;

/* Read to wztoe RX buffer with offset address of 8 */
sock_num = 2;
offset_addr = 8;
val = *(volatile uint32_t *)(WZTOE_SOCKET_RXBUF_BASEADDR(sock_num) + (offset_addr&0xFFFF)
  • API for TX/RX Buffer
void WIZCHIP_READ_BUF (uint32_t BaseAddr, uint32_t ptr, uint8_t* pBuf, uint16_t len)
{
uint16_t i = 0;
WIZCHIP_CRITICAL_ENTER();

for(i = 0; i < len; i++)
pBuf[i] = *(volatile uint8_t *)(BaseAddr +((ptr+i)&0xFFFF));

WIZCHIP_CRITICAL_EXIT();
}

void WIZCHIP_WRITE_BUF(uint32_t BaseAddr, uint32_t ptr, uint8_t* pBuf, uint16_t len)
{
uint16_t i = 0;
WIZCHIP_CRITICAL_ENTER();

for( i=0; i<len; i++)
*(volatile uint8_t *)(BaseAddr + ((ptr+i)&0xFFFF)) = pBuf[i];

WIZCHIP_CRITICAL_EXIT();
}

void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint32_t ptr = 0;
uint32_t sn_tx_base = 0;

if(len == 0) return;
ptr = getSn_TX_WR(sn);
sn_tx_base = (TXMEM_BASE) | ((sn&0x7)<<18);
WIZCHIP_WRITE_BUF(sn_tx_base, ptr, wizdata, len);
ptr += len;
setSn_TX_WR(sn,ptr);
}

void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint32_t ptr = 0;
uint32_t sn_rx_base = 0;

if(len == 0) return;
ptr = getSn_RX_RD(sn);
sn_rx_base = (RXMEM_BASE) | ((sn&0x7)<<18); WIZCHIP_READ_BUF(sn_rx_base, ptr, wizdata, len); ptr += len; setSn_RX_RD(sn,ptr); } ``` ### MDIO via GPIO * Port Init. ```cpp /* Set GPIOs for MDIO and MDC */ GPIO_InitTypeDef GPIO_InitDef; GPIO_InitDef.GPIO_Pin = GPIO_Pin_MDC | GPIO_Pin_MDIO; GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(GPIOx, &GPIO_InitDef); PAD_AFConfig(PAD_PB, GPIO_Pin_MDIO, PAD_AF1); PAD_AFConfig(PAD_PB, GPIO_Pin_MDC, PAD_AF1); ``` * MDIO APIs ```cpp uint32_t link(void) { return ((mdio_read(GPIOB, PHYREG_STATUS)>>SVAL)&0x01);
}

void set_link(SetLink_Type mode)
{
uint32_t val=0;
assert_param(IS_SETLINK_TYPE(mode));

if( mode == CNTL_AUTONEGO)
{
val = CNTL_AUTONEGO;
}
else
{
val = (mode & (CNTL_SPEED|CNTL_DUPLEX));
}

mdio_write(GPIOB, PHYREG_CONTROL, val);

}
  • MDIO Read/Write Functions
void output_MDIO(GPIO_TypeDef* GPIOx, uint32_t val, uint32_t n)
{
for(val <<= (32-n); n; val<<=1, n--)
{
if(val & 0x80000000)
GPIO_SetBits(GPIOx, MDIO);
else
GPIO_ResetBits(GPIOx, MDIO);

delay(1);
GPIO_SetBits(GPIOx, MDC);
delay(1);
GPIO_ResetBits(GPIOx, MDC);
}
}

uint32_t input_MDIO( GPIO_TypeDef* GPIOx )
{
uint32_t i, val=0;
for(i=0; i<16; i++)
{
val <<=1;
GPIO_SetBits(GPIOx, MDC);
delay(1);
GPIO_ResetBits(GPIOx, MDC);
delay(1);
val |= GPIO_ReadInputDataBit(GPIOx, MDIO);
}
return (val);
}

Firewall SoC with TCP/IP Offload Engine for Internet of Things

There is no doubt that the number of IoTs will increase explosively.

Gartner, Inc. forecasts that 4.9 billion connected things will be in use in 2015, up 30 percent from 2014, and will reach 25 billion by 2020.

As the IoT device continues to increase, IoT devices will be faced with the network flooding attack, such as DDoS, more frequently. However, because of its capacity of memory and MCU, nearly most IoT devices are very vulnerable to heavy network attacks and traffisc.

Weakness of these IoT device must be a great opportunity to TOE-embedded MCU, W7500. While TOE under Network attack is to reduce the MCU and memory resources of IoT device, because it is possible to protect the System of IoT device.

What is Firewall TCP/IP offload Engine for IoT?

Software TCP/IP stack

First, let’s examine the Software TCP/IP stack.

Software TCP/IP stack implemented on host system requires more capacity of extra memory and extra processing power for network communications. Normally, ARM Cortex-M core copies data from Ethernet MAC buffer to memory, analyze the received packets in memory using the software stack and then executes an appropriate process.

Software TCP/IP Stack

If network flooding attack has occurres, Cortex-M will repeatedly excute process in order to process flooding packets. Therefor, excessive number of TCP requests such as SYN-flooding attacks will overload the IoT device.

Hardware TCP/IP TOE

Hardware TCP/IP TOE

On the other hand, the hardware TCP/IP TOE, which is implemented as Hardwired logic from Ethernet MAC Layer to TCP/IP Layer, is able to protect IoT system against network attack under excessive number of flooding packet by making discard flooding packets detected.

Comparison of Software TCP/IP stack and Hardware TCP/IP TOE under the Network attack such as DDoS.

Hardware TCP/IP SoC

This means that Cortex-M does not have to handle the flooding packet even under Network attack. Further, because the TCP / IP stack processing is performed in TOE, it is possible to save the amount of memory for TCP/IP communications.

These TOE features are not to limited to the Network attack, it is also possible to expect the same performance under heavy network traffic.

We compared the network performance of software TCP/IP stack and Hardware TCP/IP TOE under DoS Attack (Syn-flood attack).

Comparison of Software and Hardware TCP/IP System
Software TCP/IP Hardware TCP/IP
Platform Pic. mbed1768 W7500_EVB
Platform Name mbed1768 W7500 EVB
Max Clock (MHz) 96 48
Flash (KB) 512 128
RAM (KB) 64 32
Use DMA O O
software RTOS + lwIP Non-OS + Fireware
Code size (KB) Flash:64.5 / RAM:35.2 Flash: 9.09 / RAM: 8.99
Compiler Web-compiler (mbed.org) keil
Test tools Iperf.exe, scapy (python)
Network configurations for Network Performancs tests

Network config

How to use iperf

Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of various parameters and UDP characteristics. Iperf reports bandwidth, delay jitter, datagram loss.

https://iperf.fr/

# ex.) host IP(192.168.77.34):port[5000], display format is Mbit/sec, interval 1 sec.
>iperf.exe -c 192.168.77.34 -p 5000 -f m -i 1
  • -c : –client host, -c will connect to the host specified.
  • -p : –port #, the server port for the server to listen.
  • -f : –format [], ‘m’ = Mbit/sec
  • -i : –interval #, Sets the interval time in seconds between periodic bandwidth through performance
Scripts for DoS Attack (Syn-flood attack)

We used the scapy (python library) as DoS Attack.

Scapy is a powerful interactive packet manipulation program. It can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery.
http://www.secdev.org/projects/scapy/

from scapy.all import
inter = input('inter(time in seconds to wait between 2packets) :')

def synFlood(src, tgt, inter):
    IPlayer = IP(src, dst=tgt)
    TCPlayer= TCP(sport=3000, dport=3000) # as your env. change source and destination port
    pkt = IPlayer / TCPlayer
    send(pkt, loop=1, inter=inter) #

#send(pkts, inter=0, loop=0, verbose=None)
#  Send packets at layer 3, using the conf.L3socket supersocket. pkts can
#  be a packet, an implicit packet or a list of them.
#  loop: send the packets endlessly if not 0.
#  inter: time in seconds to wait between 2 packets
#  verbose: override the level of verbosity. Make the function totally silent when 0.
#   * Refer to http://www.secdev.org/projects/scapy/files/scapydoc.pdf for more detail.

# as your env. change to real IP address and so on.
src = "192.168.77.253" # PC IP address
tgt = "192.168.77.34"  # target board
synFlood(src, tgt, inter)

Network performance

Network_performance

It is possible to prove that the network performance of Hardware TCP/IP TOE is better and more stable than software TCP/IP stack under SYN flood attack. In particular, when interval is 0.001sec., the network performance of TOE is 9 times better than the software TCP/IP stack even though the platform embedded software TCP/IP stack is better than TOE platform.

It is confirmed that the Hardware TCP/IP TOE is able to maintain the network performance even if SYN-flood attack is increased. Otherwise, it is possible to observe that the network performance of software TCP/IP stack became extremely worse according to the interval of SYN-attack.

Python Simple Script for WIZ107SR

Source Github Link

WIZ107SR

WIZ107SR is a gateway module that converts serial protocol (RS-232) into TCP/IP protocol by using W7100A.

Link WIZ107SR materials – WIZ107SR

SW – Download & Install

Script descriptions – TCPClient

  • Init. serial port number and baudrate
serial.Serial("COM1", 57600)
  • Change to serial commond mode

Change to serial command mode; when serial command switch code is ‘123’.
Just only input serial command mode switch code of 3bytes without ‘\r\n’.
Serial command mode switch code is set by using ConfigTool.

ser.write(b'123')
  • Setting TCPClient mode
ser.write(b'LP5000rn') # Source port number : ex.) 5000
ser.write(b'RP3000rn') # TCP server port number : ex.) 3000
ser.write(b'RH192.168.10.100rn') # TCP server IP address : ex.) '192.168.10.100'
ser.write(b'OP0rn') # Set TCP Client mode : OP0 - TCPClinet
ser.write(b'SVrn') # Save Setting
ser.write(b'RTrn') # Reboot
  • Send
ser.write(b'hellorn')
  • recv
serial_recv_buf = 10
line = ser.read(serial_recv_buf)

FAQ; How know the status of TCP connections ?

We can know the TCP connection by using 8pin.

In the initial time, this pin is INPUT for Hardware Trigger(for
serial command mode). After that, this pin is OUTPUT for
connection status. When the connection is established, this pin
goes Low. And, it will go HIGH when connection is closed.

AT Commands for Serial-to-Ethernet, WIZ107SR

WIZ107SR is a gateway module that converts serial protocol (RS-232) into TCP/IP protocol by using W7100A.

WIZ107SR Link (More detail)

## Simple Commands for WIZ107SR AT_COMMAND

  • Setting for TCP Server
    //after Network Config.
    LP5000\r\n    //Set Local port '5000'
    OP1\r\n    //Set TCP Server mode
    SV\r\n    //Save Setting
    RT\r\n    //Reboot
  • Setting for TCP Client
    //after Network Config.
    LP5000\r\n    //Set Local port '5000'
    RP3000\r\n    //Set TCP server port '3000'
    RH192.168.10.100\r\n    //Set TCP server IP '192.168.10.100'
    OP0\r\n    //Set TCP Client mode
    SV\r\n    //Save Setting
    RT\r\n    //Reboot
  • Setting for UDP 
    LP5000\r\n    //Set Local port '5000'
    RP3000\r\n    //Set UDP Port '3000'
    RH192.168.10.100\r\n    //Set UDP Peer IP '192.168.10.100'
    OP3\r\n    //Set UDP mode
    SV\r\n    //Save Setting
    RT\r\n    //Reboot