summaryrefslogtreecommitdiff
path: root/src/bgpstore/bgpstore.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bgpstore/bgpstore.lisp')
-rw-r--r--src/bgpstore/bgpstore.lisp128
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 ())
+
+;;;;