diff options
Diffstat (limited to 'src/bgpstore/bgpstore.lisp')
-rw-r--r-- | src/bgpstore/bgpstore.lisp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/bgpstore/bgpstore.lisp b/src/bgpstore/bgpstore.lisp new file mode 100644 index 0000000..eb4fc2a --- /dev/null +++ b/src/bgpstore/bgpstore.lisp @@ -0,0 +1,128 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- + +(in-package :bgp-logger) + +(defun xml-top-elem-from-octets (xml-octets) + (dom:document-element + (cxml:parse xml-octets (cxml-dom:make-dom-builder)))) + +(defun new-entries (top-elem) + "Return BGP-MESSAGE's, one per prefix mentioned in TOP-ELEM. +TOP-ELEM is an XML document element." + ;; We assume that top-elem is "BGP_MESSAGE". + ;(print (describe top-elem)) + (let ((updates (dom:get-elements-by-tag-name top-elem "UPDATE")) + (new-elements nil)) + (when (> (length updates) 0) + (let ((update (aref updates 0))) + (when (string= (dom:tag-name (dom:parent-node update)) "ASCII_MSG") + (let ((templ (make-instance 'bgp-message)) + (new-prefs nil) + (octet-msgs (dom:get-elements-by-tag-name top-elem "OCTET_MSG")) + (prefixes (dom:get-elements-by-tag-name top-elem "PREFIX")) + (time (aref (dom:get-elements-by-tag-name top-elem "TIME") 0))) + + ;; Populate new-prefs. + (when (> (length prefixes) 0) + (setf new-prefs + (concatenate + 'list + new-elements + (map 'list + (lambda (p) + (list (dom:data (aref (dom:child-nodes p) 0)) + (dom:get-attribute p "label"))) + prefixes)))) + + ;; TIMESTAMP and PRECISION_TIME --> template. + (let ((ts (aref (dom:get-elements-by-tag-name time "TIMESTAMP") 0)) + (pt (aref (dom:get-elements-by-tag-name time "PRECISION_TIME") 0))) + (setf (timestamp templ) + (dom:data (aref (dom:child-nodes ts) 0))) + (setf (precision-time templ) + (dom:data (aref (dom:child-nodes pt) 0)))) + + ;; AS-PATH --> template. Note that we want AS_PATH->AS + ;; only, to avoid getting COMMUNITY->AS. + (setf (path templ) + (let ((as-paths (dom:get-elements-by-tag-name update + "AS_PATH"))) + (if (= 0 (length as-paths)) + "{}" + (let ((str "{")) + (map nil (lambda (node) + (let ((as (dom:data (aref (dom:child-nodes node) 0)))) + (setf str (concatenate 'string + str + (format nil "~A," as))))) + (dom:child-nodes (aref as-paths 0))) + (concatenate 'string + (subseq str 0 (- (length str) 1)) + "}"))))) + + ;; NEXT_HOP --> template. + (setf (nexthop templ) + (let ((nexthops (dom:get-elements-by-tag-name + update "NEXT_HOP"))) + (if (= 0 (length nexthops)) + "0.0.0.0" + (dom:data (aref (dom:child-nodes (aref nexthops 0)) 0))))) + + ;; OCTETS --> template. + (when (> (length octet-msgs) 0) + (let* ((oct (aref (dom:get-elements-by-tag-name + (aref octet-msgs 0) "OCTETS") 0)) + (txt (aref (dom:child-nodes oct) 0))) + (setf (bgp-octets templ) (dom:data txt)))) + + ;; Create new elements from new-prefs and the template. + ;(format t "templ: ~A~%" (describe templ)) + ;(format t "new-prefs: ~A~%" new-prefs) + (dolist (p new-prefs) + (push (new-bgp-message templ p) new-elements)))))) + new-elements)) + +(defun new-entry-klacks (xml-doc) + "Return a fresh BGP-MESSAGE built from XML-DOC (array of unsigned bytes)." + (let ((s (cxml:make-source xml-doc)) + (e (make-instance 'bgp-message)) + (cur-name nil)) + (do ((key (klacks:peek s) (klacks:peek s))) + ((null key) e) + (case key + (:start-element (setf cur-name (klacks:current-qname s))) + (:end-element (setf cur-name nil)) + (:characters (let ((txt (klacks:current-characters s))) + (unless (or (string= cur-name "OCTET_MSG")) + (setf (slot-value e (intern cur-name)) txt))))) + (klacks:consume s)))) + +(defun marker (mark) + (format t mark) + (force-output)) + +(defun start-bgpstore (host port) + (with-connection *db-spec* + (let ((reader (new-reader host port)) + (count 0)) + (marker (format nil "~A: bgpstore started " + (iso-date (get-universal-time) t))) + (do ((e (next-xml-blurb reader "BGP_MESSAGE") + (next-xml-blurb reader "BGP_MESSAGE"))) + ((null e)) + (dolist (obj (new-entries (xml-top-elem-from-octets e))) + (insert-dao obj) + (incf count) + (if (= 0 (mod count 10000)) + (marker (format nil "~%~A: ~A " + (iso-date (get-universal-time) t) + count)) + (if (= 0 (mod count 1000)) + (marker "*") + (if (= 0 (mod count 100)) + (marker ".")))))) + (close-reader)))) + +(defun stop-bgpstore ()) + +;;;; |