Escolar Documentos
Profissional Documentos
Cultura Documentos
nadychen
Outline
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
●
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
Introduction
A light-weight implementation for TCP/IP
Suitable for embeded system with tens of
kilobytes of free RAM and room for around 40
kilobytes of code ROM
The latest lwip is 1.4.0
Introduction
Features:
IP including packet forwarding over multiple
network interface
TCP with congestion control, RTT estimation
and fast recovery/fast retransmit
Specialized no-copy API for enhanced
performace
Berkely socket API
Outline
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
Architecture
1.Mail boxes
2.Mutexes (but mutex is replaced by sem)
3.Counting semaphores
4.Thread
Architecture
void sys_arch_protect(void)
void sys_arch_unprotect(void)
cyg_thread_self
cyg_mutex_lock
cyg_mutex_unlock
Architecture
tcpip_thread
sys_timeouts_mbox_fetch
next_timeout -> timeoutA -> timeoutB -> …
ordered from small to big
Architecture
Application
main()
ip_input IP
TCPIP_MSG_INPKT
ip_output_if
thread()
Input_
input_thread cmd_eth_isr
return CYG_ISR_CALL_DSR
wait
semaphore:delivery cmd_eth_dsr
sc->state |= ETH_DRV_NEEDS_DELIVERY
post
semaphore:delivery
call
sc->funs->deliver == cml_eth_deliver
Architecture
cyg_netdevtab_entry_t
cml_eth_netdev0
device_instance
cme_vif
cml_eth0_priv_data
sc
u16_t unit = 0
macaddr[ETH_ADDR_LEN]
eth_drv_sc
cml_eth_sc0
dev_name = eth0
deiver_private
sc_arpcom
(netif)
{
Ip, netmask, gw
char name[2] = et
u8_t num = 0
state
}
Architecture
How to combine NetDev with ECOS and LWIP?
extern cyg_netdevtab_entry_t __NETDEVTAB__[], __NETDEVTAB_END__
CYG_HAL_TABLE_BEGIN(__NETDEVTAB__, netdev);
CYG_HAL_TABLE_END(__NETDEVTAB_END__, netdev);
Define LABEL:
__NETDEVTAB__ is ”.section ecos.table.netdev.begin”
__NETDEVTAB_END__ is ”.section ecos.table.netdev.finish”
Architecture
How to combine NetDev with ECOS and LWIP?
cyg_netdevtab_entry_t cml_eth_netdev0 CYG_HAL_TABLE_ENTRY(netdev)
How to combine NetDev with ECOS and LWIP?
target.ld:
.devtab ALIGN (0x4) : { . = .; KEEP(*( SORT (.ecos.table.*))) ; } > ram
sort by .ecos.table.* ,
then __NETDEVTAB__, cml_eth_netdev0, __NETDEVTAB_END__
Outline
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
memp_memory
memp_memory[]
memp_tab[MEMP_MAX]:
stored in link head for each kind of memory
next == 0 memp_num[MEMP_MAX]:
how many blocks?
memp_sizes[MEMP_MAX]:
how many bytes in one block?
… ...
next
memp_tab
[MEMP_PBUF_POOL] next
data
… ...
Pbuf
struct pbuf {
struct pbuf *next;
void *payload;
u16_t tot_len;
u16_t len;
u16_t flags;
u16_t ref;
};
Pbuf
●
struct pbuf *next;
next pbuf in singly linked pbuf chain
void *payload;
pointer to the actual data in the buffer
Pbuf
u16_t tot_len;
total length of this buffer and all next buffers in
chain belonging to the same packet
u16_t len;
length of this buffer
Pbuf
u16_t flags;
flags telling the type of pbuf
u16_t ref;
reference count
Pbuf
PBUF_POOL:
for driver, fast and suitable for interrupt.
PBUF_RAM:
header is fixed, payload is pointed to the dynamic
memory.
PBUF_ROM:
PBUF_REF:
header is fixed, payload is assigned by caller.
Pbuf PBUF_RAM
Pbuf PBUF_ROM
Pbuf PBUF_POOL
Pbuf Functions
void pbuf_init(void);
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag);
void pbuf_realloc((struct pbuf *p, u16_t new_len);
u8_t pbuf_free(struct pbuf *p);
1 → 2 → 3 becomes … 1→3
3 → 3 → 3 becomes 2 → 3 → 3
1 → 1 → 2 becomes … … 1
1 → 1 → 1 becomes … … ...
Pbuf Functions
u8_t pbuf_clen(struct pbuf *p);
count number of pbufs in a chain
void pbuf_ref(struct pbuf *p);
increment the reference count of the pbuf
err_t * pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
err_t * pbuf_copypartial(struct pbuf *buf, void *dataptr, u16_t len,
u16_t offset);
err_t * pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
copy application supplied data into a pbuf
Pbuf Functions
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment);
next
payload
len
tot_len
flags ref
A negative value decreases the header size
header
header_size_increment
…
Pbuf Functions
void pbuf_queue(struct pbuf *p, struct pbuf *n);
struct pbuf * pbuf_dequeue(struct pbuf *p);
pbuf_queue(p1,p2); p2 = pbuf_dequeue(p1);
pbuf_queue(p1,p3); … do something ...
pbuf_free(p2);
P1 P2 P3 P1 P2 P3
tot=3 ref=2 ref=2 tot=3 ref=2 ref=2
void pbuf_chain(struct pbuf *h, struct pbuf *t);
struct pbuf * pbuf_dechain(struct pbuf *p);
pbuf_chain(p1,p2); p = pbuf_dechain(p1);
pbuf_chain(p1,p3); (p == P1-1)
P1 P2 P3 P1 P2 P3
tot=9 ref=2 ref=2 tot=1 ref=2 ref=2
P1-1 P1-1
P2-1 P3-1 P2-1 P3-1
ref=2 ref=1
P1-2 P1-2
P2-2 P3-2 P2-2 P3-2
ref=2 ref=2
Pbuf Functions
void pbuf_cat(struct pbuf *h, struct pbuf *t);
pbuf_cat(p1,p2);
P1 P2 P1 P2
tot=3 ref=1 tot=6 ref=1
target.ld
__heap1 = ALIGN (0x8);
__heap1_end = 0x80000000 + RAM_SIZE*0x100000;
cacheable and RAM_SIZE*1MB
mem.c : void initMem(void)
heapstart = __heap1;
heapsize = __heap1_end - __heap1;
malloc/free
g_nodelist
size:
size of this chunk size = 0 Block0: 16 bytes
preceding: preceding
size of the preceding chunk blink = 0
head node flink
size size = 0 Block1: 32 bytes
g_heapstart preceding
preceding
heapbase node blink
size flink
...
preceding ...
...
blink
...
flink = 0 ...
g_heapend size = 0 Block18: 4 Mbytes
heap preceding
heapend space
blink
... flink
tail node
size blink and flink:
preceding supports a doubly linked list
Outline
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
TCP - States
TCP - States
Slow start:
When start, congestion window size(cwnd) is one
maximum segment size(mss).
cwnd increases it by 1 mss for each ACK received.
cwnd = cwnd + 1
Congestion avoidance:
cwnd is larger than slow start threshold(ssthresh).
cwnd increases one mss each RTT
cwnd = cwnd + mss*mss/cwnd
TCP - Slow start
Congestion Window
starts with one MSS
TCP - Congestion avoidance
TCP – Congestion Control
Fast retransmit:
If TCP sender receives three duplicate ACK with
the same ACK number
The segment with the next higher sequence
number was dropped
The sender will retransmit the packet that was
presumed dropped before waiting for its timeout.
After fast retransmit, half of current cwnd is saved
as ssthresh, and cwnd will be equal to mss.
ssthresh = cwnd / 2, cwnd = 1
Enter slow start
TCP – Congestion Control
Fast recovery:
After fast recovery, half of current cwnd is saved as
ssthresh, and cwnd will be equal to ssthresh+3.
ssthresh = MAX(cwnd/2, 2)
cwnd = ssthresh + 3
Enter congestion avoidance
TCP – Congestion Control
Congestion Control Mechanisms of TCP
cwnd 1, Slow - start phase, if cwnd ssthresh
cwnd 1 / cwnd , Congestion avoidance, if cwnd ssthresh 傳送端
cwnd
cwnd / 2, if congestion (receive triple - duplicate ACK)
1, upon timer expiry
triple dup-ACK
retransmit first
Fast lost packet
Recovery
TCP – Congestion Control
tcp_write() tcp_receive()
Transport layer
tcp_enqueue() tcp_process()
tcp_output() tcp_input()
tcp_timewait_pcbs tcp_listen_pcbs
tcp_input()
tcp_slowtmr() tcp_active_pcbs
called every 500 ms
1.Retransmission time-out
2.SYN_RCVD time-out 20 s
3.LAST_ACK time-out 120 s
4.TIME_WAIT time-out 120 s
TCP_MSL=60 s
TCP
UDP
udp_send()
udp_input() Transport layer
udp_output()
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
Socket API - 1
#define accept(a,b,c) lwip_accept(a,b,c)
#define bind(a,b,c) lwip_bind(a,b,c)
#define shutdown(a,b) lwip_shutdown(a,b)
#define close(s) lwip_close(s)
#define connect(a,b,c) lwip_connect(a,b,c)
#define getsockname(a,b,c) lwip_getsockname(a,b,c)
#define getpeername(a,b,c) lwip_getpeername(a,b,c)
#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e)
#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e)
#define listen(a,b) lwip_listen(a,b)
Socket API - 2
#define recv(a,b,c,d) lwip_recv(a,b,c,d)
#define read(a,b,c) lwip_read(a,b,c)
#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
#define send(a,b,c,d) lwip_send(a,b,c,d)
#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f)
#define socket(a,b,c) lwip_socket(a,b,c)
#define write(a,b,c) lwip_write(a,b,c)
#define select(a,b,c,d,e) lwip_select(a,b,c,d,e)
#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c)
Socket API - 3
SOCKET
SOCKETAPI
API lwip_API
lwip_API netconn_API
netconn_API
bind
bind lwip_bind
lwip_bind netconn_bind
netconn_bind
listen
listen lwip_listen
lwip_listen netconn_listen
netconn_listen
connect
connect lwip_connect
lwip_connect netconn_connect
netconn_connect
accept
accept lwip_accept
lwip_accept netconn_accept
netconn_accept
recv
recv lwip_recv
lwip_recv netconn_recv
netconn_recv
send
send lwip_send
lwip_send netconn_send
netconn_send
write
write lwip_write
lwip_write netconn_write
netconn_write
close
close lwip_close
lwip_close netconn_close
netconn_close
Socket API - 4
socket_thread:
Berkely socket API
lwip_XXX
netconn_XXX
tcpip_thread:
do_XXX
Socket API - 5
TASK 1 TASK 2 TASK 3
application
application tcpip_thread
tcpip_thread tcpip_thread
tcpip_thread
socket
socketAPI
API MSG_API
MSG_API MSG_INPKT
MSG_INPKT
lwip_bind
lwip_bind…
… do_bind
do_bind…
… ip_input
ip_input
netconn_bind
netconn_bind…
… raw_input
raw_input
udp_input
udp_input
tcp_input
tcp_input
icmp_input
icmp_input
Socket API - 6
Single Application
TASK
TASK11
(application
(application1)
1) TASK
TASK22
mbox
mbox
recv accept (tcpip_thread)
(tcpip_thread)
mbox mbox
TASK
TASK33
(tcpip_thread)
(tcpip_thread)
Socket API - 7
Multi Application
TASK
TASK11
(application
(application1)
1)
recvmbox acceptmbox
TASK
TASK22
mbox
mbox (tcpip_thread)
(tcpip_thread)
TASK
TASKNN
(application
(applicationN)
N)
recvmbox acceptmbox
TASK
TASK33
(tcpip_thread)
(tcpip_thread)
Socket API - 8
API types:
TYPE 1
CONNECT, BIND, LISTEN, CLOSE,
SEND. WRITE
TYPE 2
ACCEPT, RECV
Socket API - 9
TYPE 1
sys_mbox_fetch
do_connect
do_connect
TCPIP_MSG_API
tcp_connect(){
sys_mbox_post pcb->connected = do_connected
sys_arch_sem_wait pcb->state = SYN_SENT
tcp_enqueue()
netconn_connect mbox
mbox tcp_output()
netconn_connect
}
tcp_input() →
tcp_process(){
switch case: SYN_SENT
pcb->connected
}
do_connected
do_connected
sys_sem_signal
Socket API - 10
TYPE 2
sys_mbox_trypost recv_xxx
recv_xxx
(raw,tcp,udp)
(raw,tcp,udp)
sys_arch_mbox_fetch
lwip_recvfrom
lwip_recvfrom recvmbox
recvmbox
netconn_recv_data
netconn_recv_data pbuf
lwip_select
lwip_select select_cb_list
select_cb_list
fd_set
Outline
●
Introduction
●
System Architecture
●
Memory Management
●
memp_memory
●
Pbuf
malloc/free
●
Protocol
●
Socket API
●
How to porting lwip
How to porting lwip
svn co http://asfs/svn/ip3210_bsp/trunk/bsp
ip3210-bsp
svn co http://asfs/svn/assw/trunk/ecos-2.0
download ecos-3.0
porting lwip from ecos-3.0 to ecos-2.0
download lwip-1.4.rc
upgrade lwip to 1.4
How to porting lwip
lwip config
don't copy io/eth/v3_0/cdl/eth_drivers.cdl to ecos-
2.0
ldd ecos-2.0/tools/bin/configtool to show libs what
we need?
use configtool to open ecos.ecc and append
acrospeed template with network
add ”common ethernet support”, but uncheck
”support for stand-alone network stack”
add ”lwip” and check ”Ethernet support”, but
uncheck ”SLIP”, ”PPP” and ”Support loop interface”
set parameters for some buffer size, then save
How to porting lwip
How to porting lwip
CYGPKG_NET_LWIP
gcc compiler option: -fno-builtin
Don't recognize built-in functions that do not begin
with __builtin_ as prefix
Ex: ”printf” doesn't transfer to become ”puts”,
because ”puts” is not implemented.
How to porting lwip
thread priority
input_thread and tcpip_thread
cyg_start() and cyg_scheduler_start()
cyg_start is replaced by os_start in os_api.c
main function is the major thread created by
cyg_start
then cyg_scheduler_start is called by
cyg_start
How to porting lwip
eth_drv_alloc_buf()
pbuf pbuf pbuf
next next next
payload payload payload
... ... ...
ref ref ref
data unused unused
data pbuf pbuf
data data data bufp