! Slow ether module for (Moose) INet proceess, GDMR, Jan 1988 ! This module contains an external procedure which is called by the main ! dispatcher to send a buffer out to the ether, and an autonomous process ! which takes packets from the ether and fills in the relevant fields in the ! buffer before putting it on the inbound IP queue. %constinteger inbound priority = 7 %constinteger inbound size = 10240 %constinteger IP protocol type = 6 %include "INet:Common_Formats.Inc" %include "INet:Utility.Inc" %include "GDMR_E:2Meg.Inc" !! %include "INet:Dump.Inc" %externalpredicatespec FS lookup(%string(31) what, %integername value) %systemroutinespec phex(%integer x) %externalrecord(semaphore fm)%spec dispatch semaphore %externalrecord(queue fm)%spec IP inbound queue %externalinteger slow ether address %externalrecord(non peer info fm)%namespec sp %ownrecord(mailbox fm)%name ether mailbox %ownrecord(semaphore fm) TX semaphore = 0 %ownrecord(ether request fm) TX request = 0 %ownrecord(mailbox fm) TX response = 0 %ownrecord(semaphore fm) RX semaphore = 0 %ownrecord(ether request fm) RX request = 0 %ownrecord(mailbox fm) RX response = 0 %externalroutine slow ether outbound(%record(buffer fm)%name b) ! Send the specified buffer on its way as protocol type 6. Note that ! ether addresses are formed from IP addresses by taking the low-order ! 8 bits worth -- assuming class-C addresses, this would be the "address- ! within-network" part. %owninteger TX sequence = 0 %record(ether request fm)%name r %integer target !! printstring("Slow ether outbound: "); phex(addr(b)) !! write(b_bytes, 1); newline !! dump(byteinteger(addr(b_IP header)), b_bytes) target = b_IP peer & 255 target = 0 %if target = 255; ! Broadcast TX sequence = TX sequence + 1 TX request_code = ether write TX request_tag = TX sequence TX request_ra = target TX request_type = IP protocol type TX request_buffer == byteinteger(addr(b_IP header)) TX request_bytes = b_bytes send message(TX request, ether mailbox, TX response) sp_ether packets out = sp_ether packets out + 1 sp_ether bytes out = sp_ether bytes out + b_bytes r == receive message(TX response) %if r_tag # TX sequence %start pdate printstring("INet slow ether: dud tag ") phex(r_tag); space; phex(TX sequence) newline sp_ether errors out = sp_ether errors out + 1 %else %if r_status # ether success pdate printstring("INet slow ether: ") printstring(ether errors(r_status)) newline sp_ether errors out = sp_ether errors out + 1 %finish %if b_next queue == nil %start !! printstring("No next queue"); newline release buffer(b) %else b_stamp = msecs timestamp %if b_flags & requeue flag # 0 %start !! printstring("Requeue on "); phex(addr(b_next queue)); newline requeue(b, b_next queue) %else !! printstring("Enqueue on "); phex(addr(b_next queue)); newline enqueue(b, b_next queue) %finish %finish %end %routine inbound process %owninteger RX sequence = 0 %record(buffer fm)%name b %record(ether request fm)%name r open input(2, ":N"); select input(2) open output(2, ":T"); select output(2) !! printstring("Slow inbound handler started"); newline %cycle b == claim buffer %if b == nil %start printstring("No buffers??"); newline %stop %finish !! printstring("Inbound buffer at "); phex(addr(b)); newline RX sequence = RX sequence + 1 RX request_code = ether read RX request_tag = RX sequence RX request_type = IP protocol type RX request_buffer == b_data(32) send message(RX request, ether mailbox, RX response) r == receive message(RX response) %if r_tag # RX sequence %start pdate printstring("INet slow ether: dud tag ") phex(r_tag); space; phex(RX sequence) newline sp_ether errors in = sp_ether errors in + 1 release buffer(b) %else %if r_status # ether success pdate printstring("INet slow ether: ") printstring(ether errors(r_status)) newline sp_ether errors in = sp_ether errors in + 1 release buffer(b) %else b_bytes = r_bytes b_IP header == record(addr(b_data(32))) b_next queue == nil sp_ether packets in = sp_ether packets in + 1 sp_ether bytes in = sp_ether bytes in + b_bytes !! printstring("Received "); write(b_bytes, 0) !! printstring(" into "); phex(addr(b)); newline !! dump(byteinteger(addr(b_IP header)), b_bytes) enqueue(b, IP inbound queue) signal semaphore(dispatch semaphore) %finish %repeat %end %externalroutine start slow ether ! Set up mailboxes, etc, register ourselves as protocol 6, and start ! the receiver process. %record(process fm)%name p %record(ether request fm)%name r %integer x %label start inbound %if FS lookup(ether mailbox name, x) %start ether mailbox == record(x) %else printstring("No slow ether mailbox??"); newline %stop %finish setup semaphore(TX semaphore) setup mailbox(TX response, TX semaphore) setup message(TX request, size of(TX request)) setup semaphore(RX semaphore) setup mailbox(RX response, RX semaphore) setup message(RX request, size of(RX request)) RX request_code = ether register RX request_type = IP protocol type send message(RX request, ether mailbox, RX response) r == receive message(RX response) %if r_status # ether success %start printstring("Register: "); printstring(ether errors(r_status)) newline %stop %finish RX request_code = ether station address send message(RX request, ether mailbox, RX response) r == receive message(RX response) %if r_status # ether success %start printstring("Enquire address: "); printstring(ether errors(r_status)) newline %stop %finish slow ether address = r_context p == create process(inbound size, addr(start inbound), inbound priority, nil) !! printstring("INet slow ether handler started"); newline %return start inbound: inbound process %end %end %of %file