home *** CD-ROM | disk | FTP | other *** search
- ;;******************************************************************************
- ;; bridge.inc bridge.inc
- ;;******************************************************************************
- ;;
- ;; Copyright (C) 1989 Northwestern University, Vance Morrison
- ;;
- ;;
- ;; Permission to view, compile, and modify for LOCAL (intra-organization)
- ;; USE ONLY is hereby granted, provided that this copyright and permission
- ;; notice appear on all copies. Any other use by permission only.
- ;;
- ;; Northwestern University makes no representations about the suitability
- ;; of this software for any purpose. It is provided "as is" without expressed
- ;; or implied warranty. See the copywrite notice file for complete details.
- ;;
- ;;******************************************************************************
- ;;
- ;; Bridge.inc provides ethernet bridge cababilities. Bridge will do bridging
- ;; between the interfaces provided to it. It will also act like a IF object
- ;; and return packets that are directed to any of its interfaces.
- ;;
- ;; The functions provided by this file are
- ;;
- ;; BDG_DECLARE name, start_ifs, end_ifs, forward_ip
- ;; BDG_DEFINE name
- ;; BDG_IF_R_ACCESS_out_BX_CX_ES name, no_packet
- ;; BDG_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
- ;; BDG_IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
- ;; BDG_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name, no_buffer
- ;; BDG_IF_W_WRITE_in_CX_const_BX_BP_ES name
- ;; BDG_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
- ;; BDG_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- ;;
- ;; Variables set by this module
- ;;
- ;; bdg_&name&_declared ;; one if this interface exists
- ;; if_&name&_address ;; the hardware address
- ;; if_&name&_mtu ;; the maximum trans unit
- ;;
- ;;******************************************************************************
-
-
- ;;******************************************************************************
- ;; BDG_DECLARE name, start_ifs, end_ifs, forward_ip
- ;; BDG_DECLARE declares a bridge made up of the ifs [start_ifs..end_ifs].
- ;; All of these ifs are assumed to be declared to be PROMISCUOUS and
- ;; if 'forward_ip' is not blank, then IP broadcasts and ARPS will be
- ;; forwarded, otherwize they will not
- ;;
- BDG_DECLARE MACRO name, start_ifs, end_ifs, forward_ip
- .errb <name>
- .errb <start_ifs>
- .errb <end_ifs>
-
- if name ne 1
- .err ;; you are only alowed 1 bridge and it must be
- ;; named '1'
- endif
-
- .DATA
- bdg_&name&_declared = 1
- bdg_&name&_start_ifs = start_ifs-1
- bdg_&name&_end_ifs = end_ifs
- global bdg_&name&_table_ptr:word ;; holds segement for table
-
- ifnb <forward_ip>
- bdg_&name&_forw_ip = 1
- else
- bdg_&name&_forw_ip = 0
- endif
- .CODE
- ENDM
-
-
- ;;******************************************************************************
- ;; BDG_DEFINE name
- ;; sets asside memory for the bridge and initializes it.
- ;; routine is a no-op if 'name' was not declared
- ;;
- BDG_DEFINE MACRO name
- LOCAL loop1, loop2, loop3, table
- .errb <name>
-
- ifdef bdg_&name&_declared
- .data
- bdg_&name&_table_ptr dw ? ;; holds segment address of tab
- .FarData?
- table db 65535 dup (?) ;; set aside a whole segment
- ;; for the bridge table
-
- .CODE
- mov AX, SEG table
- mov bdg_&name&_table_ptr, AX ;; remember where the table is
-
- mov ES, AX
- xor DI, DI
- mov CX, 32768
- xor AX, AX
- rep
- stosw ;; null the bridge table
-
- endif
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_R_ACCESS_out_BX_ES name, no_packet
- ;; IF_R_ACCESS waits for the next packet to come from the the board
- ;; associated with 'name' and returns a pointer to the begining of
- ;; an ethernet packet in BX:ES. CX holds the length of the packet
- ;; R_ACCESS jumps to 'no_packet' if there are no packets waiting to
- ;; be read in
- ;;
- BDG_IF_R_ACCESS_out_BX_CX_ES MACRO name, no_packet
- local got_packet, forward_all, forward, not_me, drop
- local broadcast, broadcast_drop, around
- .errb <no_packet>
-
- IF_R_ACCESS_out_BX_CX_ES name, no_packet
-
- mov AX, ES:[BX+4] ;; is this my ethernet address?
- cmp AX, word ptr if_&name&_address+4
- jnz not_me
- mov AX, ES:[BX+2]
- cmp AX, word ptr if_&name&_address+2
- jnz not_me
- mov AX, ES:[BX]
- cmp AX, word ptr if_&name&_address
- jz got_packet
- not_me:
-
- mov BP, DS ;; save DS
- mov SI, BX
-
- mov AX, ES
- mov ES, bdg_1_table_ptr ;; ES:0 points to the table
- mov DS, AX ;; DS:SI points to the packet
-
- add SI, 6 ;; skip to source address of the packet
-
- mov DI, [SI+4] ;; compute hash function ((LSB+MSB) * 8 mod 65k)
- xor DI, [SI+2]
- shl DI, 1
- shl DI, 1
- shl DI, 1
- movsw ;; save the ethernet address
- movsw
- movsw
- mov AL, name ;; and the fact that it is on this interface
- stosb
-
- sub SI, 12 ;; restore SI to the begining of the packet
-
- test byte ptr [SI], 1H ;; is it a broadcast
-
- jnz broadcast
-
- mov DI, [SI+4] ;; compute hash function ((LSB+MSB) * 8 mod 65k)
- xor DI, [SI+2]
- shl DI, 1
- shl DI, 1
- shl DI, 1
-
- cmpsw
- jnz forward_all ;; didn't find in table
- cmpsw
- jnz forward_all ;; didn't find in table
- cmpsw
- jnz forward_all ;; didn't find in table
- mov DS, BP ;; restore DS
- mov AL, ES:[DI]
- cmp AL, name
- jnz forward
- drop:
- IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
- jmp no_packet
-
- forward:
- mov BP, CX
- IRP idx, <1,2,3,4,5,6,7,8>
- local next
- if (idx le bdg_1_end_ifs) and (idx gt bdg_1_start_ifs)
- if idx ne (name+bdg_1_start_ifs)
- cmp AL, idx
- jnz next
- IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
- mov SI, BX
- IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- mov CX, BP
- IF_W_WRITE_in_CX_const_BX_BP_ES idx
- next:
- endif
- endif
- endm
- jmp drop
-
- forward_all:
- mov DS, BP ;; restore DS
- mov BP, CX
- IRP idx, <1,2,3,4,5,6,7,8>
- if (idx le bdg_1_end_ifs) and (idx gt bdg_1_start_ifs)
- if idx ne (name+bdg_1_start_ifs)
- mov CX, BP
- IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
- mov SI, BX
- IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- mov CX, BP
- IF_W_WRITE_in_CX_const_BX_BP_ES idx
- endif
- endif
- endm
- jmp drop
-
- broadcast:
- mov AX, DS ;; restore ES
- mov ES, AX
- mov DS, BP ;; restore DS
-
- if bdg_1_forw_ip eq 0 ;; should we drop this because it is an IP or ARP packet?
- mov AX, word ptr [SI+12]
- cmp AX, 0008H ;; is it an IP packet
- jz broadcast_drop
- cmp AX, 0608H ;; is it an ARP packet
- jz broadcast_drop
- endif
-
- ;; if we don't drop it, then we must send it to all the interfaces
- push ES
- mov BP, CX
- IRP idx, <1,2,3,4,5,6,7,8>
- if (idx le bdg_1_end_ifs) and (idx gt bdg_1_start_ifs)
- if idx ne (name+bdg_1_start_ifs)
- mov CX, BP
- IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
- mov SI, BX
- IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- mov CX, BP
- IF_W_WRITE_in_CX_const_BX_BP_ES idx
- endif
- endif
- endm
- pop ES
-
- broadcast_drop:
- ;; in either case, we also send the packet up to the higher level protocols
- mov CX, BP ;; restore the length
- got_packet:
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
- ;; After the client is through processing the packet returned by
- ;; IF_R_ACCESS, IF_R_FREE must be called to inform 'name' that the
- ;; memory that the packet was in can be reused for future packets.
- ;;
- BDG_IF_R_FREE_const_BX_CX_BP_SI_DI_ES MACRO name
- local inside
- .errb <name>
-
- IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
- ENDM
-
-
- ;;******************************************************************************
- ;; BDG_IF_R_CONT_in_BX_CX_ES name, ok
- ;; IF_R_CONT determines if the packet returned by R_ACCESS in BX:ES
- ;; of length CX is continuous. If it is it jumps to 'ok' otherwise
- ;; it just returns
- ;;
- BDG_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES MACRO name, ok
- .errb <ok>
-
- IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_W_ACCESS_in_CX_out_DI_ES name, no_buffer
- ;; IF_W_ACCESS returns a pointer to an output buffer for a packet. The
- ;; pointer is returned in DI:ES. If the ouptut buffer is busy, this
- ;; routine will jump to 'no_buffer'. The output buffer min(CX, 1536)
- ;; bytes long
- ;;
- BDG_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP MACRO name, no_buffer
- .errb <no_buffer>
-
- IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name,no_buffer
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_W_WRITE_in_CX name
- ;; IF_W_WRITE actually signals the ethernet board to write a packet to
- ;; the ethernet. The packet is assumed to be in the buffer returned by
- ;; IF_W_ACCESS. CX is the length of the packet to send.
- ;;
- BDG_IF_W_WRITE_in_CX_const_BX_BP_ES MACRO name
- .errb <name>
-
- IF_W_WRITE_in_CX_const_BX_BP_ES name
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_SET_ADDRESS_in_SI name
- ;; IF_SET_ADDRESS_in_SI sets the hardware address to be the value
- ;; pointed to by SI. Note this function may be a no-op if the
- ;; hardware address cannot be set (ETHERNET for example)
- ;;
- BDG_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES MACRO name
- .errb <name>
-
- IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_COPY_in_CX_SI_DI_ES name
- ;; IF_COPY_in_CX_SI_DI_ES copys a packet from the input buffer (pointed
- ;; to by SI and the segement register given in IF_DECLARE) to an output
- ;; buffer (pointed to by DI and dest_reg) of length CX. It assumes the
- ;; output buffer is contiguous. (and the caller shouln't care if the
- ;; input buffer is contiguous)
- ;;
- BDG_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES MACRO name
- local wrap, done
- .errb <name>
-
- IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- ENDM
-
-