Web 51 - Zpracovani Ethernet Paketu

Web 51 - Obsluha serioveho kanalu  software.html  Web 51 - WEB51 TCP sockets

Hlavní smyčka

Hlavní smyčka serveru Web 51 je složena z několika více-méně povinných částí, shrnutých v knihovním modulu web51.asm a uživatelských částí v ukázkových příkladech shrnutých shrnutých do modulu www8051.asm.

Složení jednotlivých částí do celkové hlavní smyčky zabezpečuje linker. Kód celé hlavní smyčky je rozdělen na několik bloků, které jsou za sebou linkovány na základě jmen segmentů. Jednotlivé sekce jsou za sebou linkovány v tomto pořadí:

Následující ukázková hlavní smyčka demonstruje zhruba ukázkovou aplikaci obsluhující www server a sériovou linku.

Celá hlavní smyčka začíná sekcí fast_begin modulu web51.

Na začátku každého průchodu smyčkou nejprve zresetujeme Watchdog obvodu 89S8252

        .section fast_begin, #alloc
;#########################################################
;  Main Loop
;#########################################################
;
mainloop:
        mov     WMCON,#RESTARTWATCHDOG  ;restart Watchdog

Při průchodu smyčkou jsou otestovány podmínky řízení toku dat (Xon/Xoff, CTS) a zahájeno případné vysílání.

.if SERIAL
        lcall   sstat                   ;scan RTS/CTS,...
.endif

Je zkontrolován obvod RTL8019 a přečtena případná hlavička přijatého paketu.

        mov     stateFlg,#0             ;clear rx_eth_bit, flagARP..flagTCP
        LCALL   rcv_pkt
        jnb     rx_eth_bit,NoRxEth

V případně přijetí paketu je zkontrolován obsah paketu na přítomnost zpracovatelných typů a známý paket (ICMP / TCP / UDP / ARP) je zpracován.

        jnb     B2B(stateFlg, flagICMP),.+6   ;jnb     flagICMP,$+6     pro překladače Keil/Intel
        lcall   ProcessICMP
        jnb     B2B(stateFlg, flagTCP),.+6
        lcall   ProcessTCP
        jnb     B2B(stateFlg, flagUDP),.+6
        lcall   ProcessUDP
        jnb     B2B(stateFlg, flagARP),.+6
        lcall   ProcessARP

Není-li přijat žádný paket, popř. je přijat nezpracovávatelný paket, je otestováno uplynutí 1 milisekundy.

NoRxEth:jnb     bit1ms,mainloop
        clr     bit1ms
;~1 ms loop
fastloop:

Vyšli případné požadavky na zjištění MAC adresy Gateway či "telnet" protistanice

        jnb     flagArpGwRq,.+6
        lcall   ProcessArpGwRq
.if ACTIVESTACK
        jnb     flagArpPoiRq,.+6
        lcall   ProcessArpPoiRq

Je-li zjištěna MAC adresa "telnet" protistanice a povoleno případné spojení s protistanicí, zahaj TCP vyjednávání vysláním SYN paketu

        jnb     flagSynRq,.+6
        lcall   ProcessSynRq
.endif

V tomto bodě program hlavní části prochází jednotlivými sekcemi fast uživatelských modulů (uživatelského modulu, např. web8051 v případě ukázkových příkladů).

        .section fast, #alloc
;*************************************************************

Není-li otevřeno spojení s "telnet" protistanicí a je-li povoleno zahaj vyjednávání o spojení

        jnb     rxint, no23ch   ;if Not Data to send, don't make connection
        jnb     flagIPactive,no23ch ;if flash_ip_point = 0.0.0.0,
                                ;don't make connection
        mov     r7,#LASTSTACK1
        lcall   changeStack
        mov     a,tcpState
        jnz     est23ch         ;if Connect Established, don't make new
        lcall   ConnectTCP1
        sjmp    no23ch

V případě otevřeného spojení s "telnet" protistanicí zkontroluj zda není větší množství nevyslaných dat v bufferu a popřípadě je odešli.

est23ch:
        jb      flag1WaitForAck,no23ch
                        ;if All previous send data is Acked
                        ;and sizeof(unsend data in Rx buffer) >= MAXCHAR/2 char
                        ;then send output packet
        mov     a,r1point
        cjne    a,#rser+(MAXCHAR/2),.+3
        jc      no23ch  ;jump if sizeof(unsend data in Rx buffer) < MAXCHAR/2
        lcall   OutTCP1 ;send all queued data
no23ch:

Po projití všech jednotlivých sekcí fast uživatelských modulů pokračuje vykonávání programu sekcí fast_end modulu web51.

        .section fast_end, #alloc
;*************************************************************

Zkontroluj uplynutí 50 ms

        djnz    slowtimer,main
        mov     slowtimer,#slowtiming
;~50 ms loop
slowloop:

Dále pokračujeme vykonáváním programu sekcí slow_begin modulu web51.

        .section slow_begin, #alloc
;*************************************************************
        clr     B2B(tcpState, stateSyn)
.if DUALSTACK
        clr     B2B(tcpStateXX, stateSyn)
        clr     B2B(tcpStateXX+1, stateSyn)
.endif

V tomto bodě program hlavní části prochází jednotlivými sekcemi slow uživatelských modulů (uživatelského modulu, např. web8051 v případě ukázkových příkladů).

	.section slow, #alloc
;*************************************************************

Nejprve vyhodnotíme časovače spojení TCP / sériový kanál ("telnetu")

;; telnet timer
;~50 ms loop
        mov     a,Retry1
        jz      no23timer
        dec     Timeout1
        mov     a,Timeout1
        jnz     no23timer
;~200 ms loop

Zopakuj vysílání případnéch nepotvrzených dat, popř. po vypršení počtu opakování spojení uzavři.

        mov     Timeout1,#ethtiming
        dec     Retry1
        mov     a,Retry1
        jz      kill23
        lcall   RetryTCP1
        ajmp    no23
kill23: lcall   CloseTCP1
        ajmp    no23

Jsou-li v bufferu jakákoliv nevyslaná data tak je odešli.

no23timer:
        mov     r7,#LASTSTACK1
        lcall   changeStack
        jnb     B2B(tcpState, stateEstablished),no23
        jbc     flag1WaitForAck,no23
        jnb     rxint,no23
        lcall   OutTCP1         ;send all queued
                                ;data, don't wait for limit MAXCHAR/2
no23:

Obdobně je vhodné se zachovat i u http spojení a po vypršení timeoutu spojení uzavřít.

;; http timer
;~50 ms loop
        mov     a,Retry2
        jz      no80
        dec     Timeout2
        mov     a,Timeout2
        jnz     no80
;~200 ms loop
        mov     Timeout2,#ethtiming
        dec     Retry2
        mov     a,Retry2
        jnz     no80
        lcall   CloseTCP2
no80:

Po projití všech jednotlivých sekcí slow uživatelských modulů pokračuje vykonávání programu sekcí slow_end modulu web51.

        .section slow_end, #alloc
;*************************************************************
        ajmp    main

Vyhodnocení přijatého Ethernet paketu

Standartně je vyhodnocení přijatého ethernetového paketu soustředěno do modulu web51.

Po přijetí paketu je v něm hledáno několik "magických" čísel, specifikujících o jaký typ paketu se jedná. Nejprve je v hlavičce paketu hledána identifikace dle RFC894 (A Standard for the Transmission of IP Datagrams over Ethernet Networks) specifikující, že se jedná o přenos IP paketu. Druhou identifikací, hledanou v hlavičce paketu je identifikace ARP paketu dle RFC826 (An Ethernet Address Resolution Protocol) specifikující, že se jedná o přenos ARP paketu.

        .section cpu_rom, #alloc
;
;**************************************************************************
ProcessEthPacket:
;;if (rx_eth_pkt.pktType == 0x0800) goto IPPacket; //IP
;;else if (rx_eth_pkt.pktType == 0x0806) goto ArpPacket; //ARP
;;else goto UnknownEthType;
        mov     a,eth_pkt_hdr_type
        xrl     a,#0x08         ;high ARP and IP ID
        jnz     UnknownEthType
        mov     a,eth_pkt_hdr_type+1
        jz      IPPacket
        xrl     a,#0x06         ;low ARP ID
        jz      ArpPacket
UnknownEthType:
        ret                     ;Unknown ID of Ethernet packet
;**************************************************************************
;Type of ethernet packet = 0806h ARP
ArpPacket:
        setb    B2B(stateFlg, flagARP)
        ret
Z přijatého IP paketu dle RFC791 (Internet Protocol) je do pomocného pole v RAM procesoru přenesen blok 12 byte.
VersionIHLType of ServiceTotal Length
IdentificationFlagsFragment Offset
Time to LiveProtocolHeader Checksum
Source Address
Destination Address
 

Destination Address je zkontrolována, zda obsahuje IP adresu Web 51. Paket určený pro jinou adresu je ignorován.

;**************************************************************************
;Type of ethernet packet = 0800h IP
NoMyIP:
        mov     WMCON,#WATCHDOG         ;disable EEPROM & DPTR'
        ret                             ;IP with IP_DSTADDR != flash_my_ip
IPPacket:
;;if (rx_eth_pkt.pkt.ip.ipheader.DstAddr == flash_my_ip) {
        mov     R7,#dwordtemp           ;buffer_addr = dwordtemp & iftemp
        mov     R5,#IP_TTL              ;source_packet_offset
        mov     R3,#12                  ;length
        lcall   short_pr2s      ;read IP_TTL & IP_PROTO & IP_CKSUM
                                ;IP_SRCADDR & IP_DSTADDR to temp var
        mov     dptr,#flash_my_ip
        mov     r0, #dwordtemp+(IP_DSTADDR-IP_TTL)
        mov     r1, #IP_ADDR_LEN
        mov     WMCON,#WATCHDOG OR EEMEN;enable EEPROM
myiploop:movx   a,@dptr
        xrl     a,@r0
        jnz     NoMyIP
        inc     dptr
        inc     r0
        djnz    r1,myiploop

Následuje otestování Source Address zda se odesílatel paketu nachází na stejné síti jako Web 51, či je nutno s ním komunikovat přes bránu (gateway).

Vyjdeme-li ze vztahů:
MY_NETWORK = ( my_ip AND network_mask )
SRC_NETWORK = ( src_ip AND network_mask )
a test MY_NETWORK == SRC_NETWORK
nahradíme jeho možnou strojovou reprezentací ( MY_NETWORK XOR SRC_NETWORK ) == 0
dojdeme několika úpravami ke vztahu (( my_ip XOR src_ip ) AND network_mask ) == 0 použitém v Web 51

;;if (((rx_eth_pkt.pkt.ip.ipheader.SrcAddr & flash_my_ip) & flash_ip_mask) != 0) {
        mov     dptr,#flash_my_ip
        mov     r0, #dwordtemp+(IP_SRCADDR-IP_TTL)
        mov     r1, #IP_ADDR_LEN
gwloop1:movx    a,@dptr
        xrl     a,@r0
        mov     @r0,a
        inc     dptr
        inc     r0
        djnz    r1,gwloop1
        mov     dptr,#flash_ip_mask
        mov     r0, #dwordtemp+(IP_SRCADDR-IP_TTL)
        mov     r1, #IP_ADDR_LEN
gwloop2:movx    a,@dptr
        anl     a,@r0
        jnz     gwloopbreak
        inc     dptr
        inc     r0
        djnz    r1,gwloop2
gwloopbreak:
        mov     WMCON,#WATCHDOG         ;disable EEPROM & DPTR'
        jz      noneedgw

I když lze v 99% předpokládat, že požadavek z cizí sítě přijde přes bránu a tím pádem má nastavenu správnou MAC adresu odesílatele, nelze se na to spolehnout. V přijatém paketu z cizí sítě proto vždy vyměníme MAC adresu odesílatele za MAC adresu brány. Tato MAC adresa je v případné odpovědi použita jako adresa příjemce. Výměnu MAC adresy však můžeme provést pouze známe-li ji. Otestujeme proto zda byla MAC adresa brány pomocí ARP dotazu již zjištěna. Je-li tento test negativní, nastavíme požadavek na vyslání ARP dotazu a přijatý paket zahodíme jako nezpracovatelný.

;;  if(mac_gateway == 0) {
        mov     r0, #mac_gateway
        mov     r1, #ETHER_ADDR_LEN
gwloop3:mov     a,@r0
        jnz     noneedarpgw
        inc     r0
        djnz    r1,gwloop3
;;    MakeArpGwRq(); return;
        setb    flagArpGwRq             ;Arp Gateway Request
        ret
;;  } else {
;;    EthRcvHdr.pktSrc = mac_gateway;
noneedarpgw:
        mov     r0, #mac_gateway
        mov     r1, #eth_pkt_hdr_src
        mov     r2, #ETHER_ADDR_LEN
gwloop4:mov     a,@r0
        mov     @r1,a
        inc     r0
        inc     r1
        djnz    r2,gwloop4
;;  }
;;}

V paketu s ověřenými IP adresami jsou hledány čísla protokolů dle RFC1700 (Assigned Numbers) a při nalezení čísla protokolu, podporovaného Web 51 je nastaven příznak odpovídajícího protokolu sdělující např. hlavní smyčce programu, že byl přijat zpracovatelný paket.

noneedgw:
;;  switch (rx_eth_pkt.pkt.ip.Proto) {
;;    case IPT_ICMP: goto protoICMP;
        mov     R0,#dwordtemp+(IP_PROTO-IP_TTL)
        mov     a,@R0
        xrl     a,#IPT_ICMP             ;proto ICMP
        jz      protoICMP
;;    case IPT_TCP:  goto protoTCP;
        xrl     a,#IPT_ICMP xor IPT_TCP ;proto TCP
        jz      protoTCP
;;    case IPT_UDP:  goto protoUDP;
        xrl     a,#IPT_TCP xor IPT_UDP  ;proto UDP
        jz      protoUDP
        ret
protoICMP:
        setb    B2B(stateFlg, flagICMP)
        ret
protoTCP:
        setb    B2B(stateFlg, flagTCP)
        ret
protoUDP:
        setb    B2B(stateFlg, flagUDP)
        ret
;;  }
;;}
;




Sponzored by LPhard Ltd. Graphics by GIMP Created by EasyPad

(c)Copyright 2000, 2001, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz

Final applications of the Web51 : www.HWgroup.cz
Web 51 - Obsluha serioveho kanalu  Obsah  Web 51 - WEB51 TCP sockets