Web 51 - Zpracovani Ethernet Paketu |
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í:
- fast_begin - je zahrnut v modulu web51
- fast - je obsažen v uživatelském modulu (modulech, např. v www8051)
- fast_end - je zahrnut v modulu web51
- slow_begin - je zahrnut v modulu web51
- slow - je obsažen v uživatelském modulu (modulech, např. v www8051)
- slow_end - je zahrnut v modulu web51
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 WatchdogPř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,... .endifJe 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,NoRxEthV 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 ProcessARPNení-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 ProcessArpPoiRqJe-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 .endifV 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 no23chV 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) .endifV 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 loopZopakuj 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 no23Jsou-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
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.
Version IHL Type of Service Total Length Identification Flags Fragment Offset Time to Live Protocol Header 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,myiploopNá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 noneedgwI 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 ;; } ;;} ;
POPIS Web51 | NOVINKY | FAQ | OBJEDNÁVKA | DOWNLOAD |
(c)Copyright 2000, 2001, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz Final applications of the Web51 : www.HWgroup.cz |