aboutsummaryrefslogtreecommitdiff
path: root/docs/j1demo/firmware/arp.fs
diff options
context:
space:
mode:
Diffstat (limited to 'docs/j1demo/firmware/arp.fs')
-rw-r--r--docs/j1demo/firmware/arp.fs225
1 files changed, 225 insertions, 0 deletions
diff --git a/docs/j1demo/firmware/arp.fs b/docs/j1demo/firmware/arp.fs
new file mode 100644
index 0000000..c6b69c7
--- /dev/null
+++ b/docs/j1demo/firmware/arp.fs
@@ -0,0 +1,225 @@
+( ARP: Address Resolution Protocol JCB 13:12 08/24/10)
+module[ arp"
+
+\ ARP uses a small cache of entries. Each entry has an age counter; new
+\ entries have an age of 0, any entry with an age >N is old.
+\
+
+
+d# 12 constant arp-cache-entry-size
+d# 5 constant arp-cache-entries
+TARGET? [IF]
+ meta
+ arp-cache-entry-size arp-cache-entries * d# 64 max
+ target
+ constant arp-size
+ create arp-cache arp-size allot
+ meta
+ arp-cache-entries 1- arp-cache-entry-size * arp-cache +
+ target
+ constant arp-cache-last
+[ELSE]
+ arp-cache-entry-size arp-cache-entries * d# 64 max constant arp-size
+ create arp-cache arp-size allot
+ arp-cache-entries 1- arp-cache-entry-size * arp-cache + constant arp-cache-last
+[THEN]
+
+: arp-foreach \ (func -- )
+ arp-cache-last 2>r
+ begin
+ 2r@ swap \ ptr func
+ execute
+ r> dup arp-cache-entry-size - >r
+ arp-cache =
+ until
+ 2r> 2drop
+;
+
+build-debug? [IF]
+: arp-.
+ dup @ hex4 space \ age
+ dup 2+ dup @ swap d# 2 + dup @ swap d# 2 + @ ethaddr-pretty space
+ d# 8 + 2@ ip-pretty
+ cr
+;
+
+: arp-dump
+ ['] arp-. arp-foreach
+;
+[THEN]
+
+: arp-del h# ff swap ! ;
+: arp-reset ['] arp-del arp-foreach ;
+: used? @ h# ff <> ;
+: arp-age-1 dup used? d# 1 and swap +! ;
+: arp-age ['] arp-age-1 arp-foreach ;
+: arp-cmp ( ptr0 ptr1 -- ptr) over @ over @ > ?: ;
+: arp-oldest \ return the address of the oldest ARP entry
+ arp-cache ['] arp-cmp arp-foreach ;
+
+\ ARP offsets
+\ d# 28 sender ethaddr
+\ d# 34 sender ip
+\ d# 38 target ethaddr
+\ d# 44 target ip
+
+d# 20 constant OFFSET_ARP_OPCODE
+d# 22 constant OFFSET_ARP_SRC_ETH
+d# 28 constant OFFSET_ARP_SRC_IP
+d# 32 constant OFFSET_ARP_DST_ETH
+d# 38 constant OFFSET_ARP_DST_IP
+
+: arp-is-response
+ OFFSET_ETH_TYPE packet@ h# 806 =
+ OFFSET_ARP_OPCODE packet@ d# 2 =
+ and
+;
+
+\ write the current arp response into the cache, replacing the oldest entry
+: !-- \ ( val ptr -- ptr-2 )
+ tuck \ ptr val ptr
+ !
+ 2-
+;
+
+\ Current packet is an ARP response; write it to the given slot in the ARP cache, ageing all others
+
+: arp-cache-write \ ( ptr -- )
+ arp-age \ because this new entry will have age d# 0
+ d# 0 over ! \ age d# 0
+ >r
+
+ d# 3 OFFSET_ARP_SRC_ETH mac-inoffset mac@n
+ r@ d# 6 + !-- !-- !-- drop
+ d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
+ r> d# 8 + 2!
+
+;
+
+\ Comparison of IP
+: arp-cmpip \ (ip01 ip23 ptr/0 ptr -- ip01 ip23 ptr)
+ dup used? if
+ dup d# 8 + 2@ d# 2 2pick d<> ?:
+ else
+ drop
+ then
+;
+
+: arp-cache-find ( ip01 ip23 -- ip01 ip23 ptr )
+\ Find an IP. Zero if the IP was not found in the cache, ptr to entry otherwise
+ d# 0 ['] arp-cmpip arp-foreach ;
+
+
+: arp-issue-whohas \ (ip01 ip23 -- ptr)
+ mac-pkt-begin
+ ethaddr-broadcast mac-pkt-3,
+ net-my-mac mac-pkt-3,
+ h# 806 \ frame type
+ d# 1 \ hard type
+ h# 800 \ prot type
+ mac-pkt-3,
+ h# 0604 \ hard size, prot size
+ d# 1 \ op (1=request)
+ mac-pkt-2,
+ net-my-mac mac-pkt-3,
+ net-my-ip mac-pkt-2,
+ ethaddr-broadcast mac-pkt-3,
+ mac-pkt-2,
+ mac-pkt-complete drop
+ mac-send
+;
+
+\ Look up ethaddr for given IP.
+\ If found, return pointer to the 6-byte ethaddr
+\ If not found, issue an ARP request and return d# 0.
+
+: arp-lookup \ ( ip01 ip23 -- ptr)
+ 2dup
+ ip-router 2@ dxor ip-subnetmask 2@ dand
+ d0<>
+ if
+ 2drop
+ ip-router 2@
+ then
+ arp-cache-find \ ip01 ip23 ptr
+ dup 0= if
+ -rot \ d# 0 ip01 ip23
+ arp-issue-whohas \ d# 0
+ else
+ nip nip 2+ \ ptr
+ then
+;
+
+\ If the current packet is an ARP request for our IP, answer it
+: arp-responder
+ \ is destination ff:ff:ff:ff:ff:ff or my mac
+ d# 3 OFFSET_ETH_DST mac-inoffset mac@n
+ and and invert 0=
+
+ net-my-mac \ a b c
+ d# 2 OFFSET_ETH_DST 2+ mac-inoffset mac@n
+ d= swap \ F a
+ OFFSET_ETH_DST packet@ = and
+
+ or
+ OFFSET_ETH_TYPE packet@ h# 806 = and
+ \ is target IP mine?
+ d# 2 OFFSET_ARP_DST_IP mac-inoffset mac@n net-my-ip d= and
+ if
+ mac-pkt-begin
+
+ d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
+ net-my-mac mac-pkt-3,
+ h# 806 \ frame type
+ d# 1 \ hard type
+ h# 800 \ prot type
+ mac-pkt-3,
+ h# 0604 \ hard size, prot size
+ d# 2 \ op (2=reply)
+ mac-pkt-2,
+ net-my-mac mac-pkt-3,
+ net-my-ip mac-pkt-2,
+ d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
+ d# 2 OFFSET_ARP_SRC_IP mac-pkt-src
+
+ mac-pkt-complete drop
+ mac-send
+ then
+;
+
+: arp-announce
+ mac-pkt-begin
+
+ ethaddr-broadcast mac-pkt-3,
+ net-my-mac mac-pkt-3,
+ h# 806 \ frame type
+ d# 1 \ hard type
+ h# 800 \ prot type
+ mac-pkt-3,
+ h# 0604 \ hard size, prot size
+ d# 2 \ op (2=reply)
+ mac-pkt-2,
+ net-my-mac mac-pkt-3,
+ net-my-ip mac-pkt-2,
+ ethaddr-broadcast mac-pkt-3,
+ net-my-ip mac-pkt-2,
+
+ mac-pkt-complete drop
+ mac-send
+
+;
+
+: arp-handler
+ arp-responder
+ arp-is-response
+ if
+ d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
+ arp-cache-find nip nip
+ dup 0= if
+ drop arp-oldest
+ then
+ arp-cache-write
+ then
+;
+
+]module