;;; -*- Mode:LISP; Package:NETWORK; Readtable:CL; Base:10 -*- #| Copyright LISP Machine, Inc. 1987 See filename "Copyright.Text" for licensing and release information. |# (export '( *network-protocol-streams* network-protocol make-network-protocol enable-network-protocols disable-network-protocols)) (defstream network-protocol () "NP-" (keyword nil) ; keyword for this protocol family (opened nil) ; t if stream ready for business (enabled nil) ; t if processing enabled (protocol nil) ; protocol types for ARP (addresses nil) ; network address list. If NIL, no ARP (address-length 0) ; length of a network address (big-endian-address-p nil) ; t if address extracted low-byte first (reset-function nil) ; function to reset processing for this protocol (close-function nil) ; function to call when this protocol is being closed (enable-function nil) ; function to enable processing for this protocol (disable-function nil) ; function to disable processing for this protocol (interrupt-function nil) ; function called at interrupt level when packet received ; if NIL, packets saved on packet-list (packet-list nil) ; list of packets awaiting :receive (special-address-function nil) ; a function to call to check if an address is special (address-printer nil) ; a function to call to return string with canonical address (get-header-function nil) ; a function to call to get a packet header (free-header-function nil) ; a function to call to free a packet header (send-packet-function nil) ; a function to call to send a packet with header (broadcast-packet-function nil) ; a function to call to broadcast a packet with header (packet-length-function nil) ; a function to call to figure packet length (for stats) (statistics-block (make-statistics-block)) ; Network statistics block maintained at clock level (packets-sent-discarded 0) ; statistic: sent packets discarded (packets-received-discarded 0) ; statistic: received packets discarded (bytes-sent-discarded 0) ; statistic: sent bytes discarded (bytes-received-discarded 0) ; statistic: received bytes discarded (protocols nil) ; alist of transport protocols above this network protocol (protocols-not-understood nil) ; list of unrecognized protocols (active-gauges nil) ; list of gauges in control panel (inactive-gauges nil) ; list of gauges not currently in control panel (gauge-name nil) ; the name of this protocol for its gauges ) (defsubst np-packets-sent (np) (aref (np-statistics-block np) STAT-PS STAT-CURR)) (defsubst np-packets-received (np) (aref (np-statistics-block np) STAT-PR STAT-CURR)) (defsubst np-bytes-sent (np) (aref (np-statistics-block np) STAT-BS STAT-CURR)) (defsubst np-bytes-received (np) (aref (np-statistics-block np) STAT-BR STAT-CURR)) (defvar *network-protocol-streams* nil "List of open network-protocols") (defop (network-protocol :update-methods) nil (create-included-methods (named-structure-p self))) (defop (network-protocol :open) (address subnet) "open a network-protocol." (unless (np-opened self) (dolist (stream *network-protocol-streams*) (when (eq (np-keyword stream) (np-keyword self)) (send stream :close) (return t))) (push self *network-protocol-streams*) (let ((func (let ((stream self)) #'(lambda (int-pkt interface sender receiver broadcast-p) (network-protocol-packet-receiver int-pkt interface stream sender receiver broadcast-p)))) list result) (labels ((make-address-form (l) (cond ((consp l) (cons (make-address-form (car l)) (make-address-form (cdr l)))) ((numberp l) l) ((eq l :address) address) ((eq l :subnet) subnet) (t nil)))) (dolist (ni *network-interfaces*) (dolist (item *protocol-configuration*) (when (and (eq (ni-keyword ni) (first item)) (setq list (assoc (np-keyword self) (cdr item)))) (pushnew (cons (first item) (second list)) (np-protocol self) :test #'equal) (delete-from-alist (np-keyword self) (ni-network-alist ni)) (push (cons (np-keyword self) (make-address-form (third list))) (ni-network-alist ni)) (delete-from-alist (np-keyword self) (ni-address-alist ni)) (let ((address (make-address-form (fourth list)))) (push (cons (np-keyword self) (ncons address)) (ni-address-alist ni)) (setq result (nconc result (ncons address)))) (delete-from-alist (second list) (ni-protocol-alist ni)) (push (cons (second list) func) (ni-protocol-alist ni)) (return t))))) (setf (np-addresses self) result)) (when (np-addresses self) (setf (get (np-keyword self) 'si::address-unparser) (np-address-printer self))) (add-network-statistics-block (np-statistics-block self)) (setf (np-opened self) t))) (defop (network-protocol :close) (&optional abort) (when (np-opened self) (when (np-enabled self) (send self :disable)) (when (np-close-function self) (funcall (np-close-function self) self abort)) (dolist (prot (np-protocols self)) (send (cdr prot) :close)) (setf (np-opened self) nil) (send self :kill-gauges) (delete-network-statistics-block (np-statistics-block self)) (without-interrupts (setq *network-protocol-streams* (delete self *network-protocol-streams*))) (dolist (ni *network-interfaces*) (delete-from-alist (np-keyword self) (ni-network-alist ni)) (delete-from-alist (np-keyword self) (ni-address-alist ni)) (let ((type (cdr (assoc (ni-keyword ni) (np-protocol self) :test #'eq)))) (when type (delete-from-alist type (ni-protocol-alist ni))))))) (defop (network-protocol :reset) nil (when (np-opened self) (and (np-reset-function self) (funcall (np-reset-function self) self)))) (defop (network-protocol :enable) nil (when (np-opened self) (unless (np-enabled self) (and (np-enable-function self) (funcall (np-enable-function self) self)) (setf (np-enabled self) t)))) (defop (network-protocol :disable) nil (when (np-enabled self) (setf (np-enabled self) nil) (dolist (x (np-packet-list self)) (free-packet (car x))) (setf (np-packet-list self) nil) (and (np-disable-function self) (funcall (np-disable-function self) self)))) (defop (network-protocol :send) (packet length interface address &optional hang-p) (declare (ignore hang-p)) (when (and (ni-enabled interface) (ni-loopback interface) (eql address (ni-address interface))) (setq interface *loopback-interface*)) (let* ((int-pkt (original-array packet)) (header (ni-sent-header-length interface)) (trailer (ni-sent-trailer-length interface)) (total-length (+ length header trailer))) (cond ((and (np-enabled self) (ni-enabled interface)) (incf (np-packets-sent self)) (incf (np-bytes-sent self) length) (setf (fill-pointer int-pkt) (ceiling total-length 2)) (incf (ni-packets-sent interface)) (incf (ni-bytes-sent interface) total-length) (let ((type (cdr (assoc (ni-keyword interface) (np-protocol self) :test #'eq)))) ;;***for print-int-pkt-status... (setf (int-pkt-bit-count int-pkt) (swap-two-bytes type)) (funcall (ni-send-function interface) int-pkt (ni-address interface) address type (ceiling total-length 2)))) (t (incf (np-packets-sent-discarded self)) (incf (np-bytes-sent-discarded self) length) (incf (ni-packets-sent-discarded interface)) (incf (ni-bytes-sent-discarded interface) length) (free-packet packet) nil)) ;Didn't send it )) (defop (network-protocol :receive) (&optional no-hang-p) (declare (values packet interface)) (cond ((np-enabled self) (or (np-packet-list self) ; packets waiting... no-hang-p ; or don't care... (np-interrupt-function self) ; or interrupt function (NEVER packets waiting!) (process-wait "Link Level Packet" #'(lambda (x) (np-packet-list x)) self)) (without-interrupts (let ((pair (pop (np-packet-list self)))) (values (car pair) (cdr pair))))))) (defop (network-protocol :print-self) (stream &optional ignore ignore) (sys:printing-random-object (self stream :type :no-pointer) (format stream "~A (~:[closed~;open~] ~:[dis~;en~]abled)" (np-keyword self) (np-opened self) (np-enabled self)))) (defop (network-protocol :set-gauges) (gauge-list) "Set the active network gauges for this network protocol" (set-gauges (np-statistics-block self) (locf (np-active-gauges self)) (locf (np-inactive-gauges self)) (np-gauge-name self) gauge-list)) (defop (network-protocol :make-gauges) (&optional (gauge-list '(:apr :aps :abr :abs))) "Add selected gauges for this network protocol" (add-gauges (np-statistics-block self) (locf (np-active-gauges self)) (locf (np-inactive-gauges self)) (np-gauge-name self) gauge-list)) (defop (network-protocol :kill-gauges) (&optional (gauge-list '(:ipr :apr :ips :aps :ibr :abr :ibs :abs))) "Delete selected gauges from a network protocol. Default is to delete all gauges" (delete-gauges (locf (np-active-gauges self)) (locf (np-inactive-gauges self)) gauge-list)) (defop (network-protocol :reset-stats) () (without-interrupts (setf (np-bytes-sent self) 0) (setf (np-bytes-received self) 0) (setf (np-packets-sent self) 0) (setf (np-packets-received self) 0) )) (defun network-protocol-packet-receiver (packet interface stream sender receiver broadcast-p) (let ((bytes (if (np-packet-length-function stream) (funcall (np-packet-length-function stream) packet (/ (ni-rcvd-header-length interface) 2)) (* 2 (fill-pointer packet))))) (cond ((np-enabled stream) (incf (np-packets-received stream)) (incf (np-bytes-received stream) bytes) (if (np-interrupt-function stream) (funcall (np-interrupt-function stream) packet interface stream sender receiver broadcast-p) (without-interrupts (setf (np-packet-list stream) (nconc (np-packet-list stream) (ncons (list packet interface sender receiver))))))) (t (incf (np-packets-received-discarded stream)) (incf (np-bytes-received-discarded stream) bytes) (incf (ni-packets-received-discarded interface)) (incf (ni-bytes-received-discarded interface) bytes) (free-packet packet))) )) (defun disable-network-protocols () (dolist (np *network-protocol-streams*) (send np :disable))) (defun enable-network-protocols () (dolist (np *network-protocol-streams*) (send np :enable)))