]>
The Tcpdump Group git mirrors - libpcap/blob - tests/visopts.py
4 This program parse the output from pcap_compile() to visualize the CFG after
8 1. Enable optimizier debugging code when configure libpcap,
9 and build libpcap & filtertest
10 ./configure --enable-optimizer-dbg
13 2. Run filtertest to compile BPF expression, save to output a.txt
14 ./filtertest EN10MB host 192.168.1.1 > a.txt
15 3. Send a.txt to this program's standard input
16 cat a.txt | tests/visopts.py
17 4. Step 2&3 can be merged:
18 ./filtertest EN10MB host 192.168.1.1 | tests/visopts.py
19 5. The standard output is something like this:
20 generated files under directory: /tmp/visopts-W9ekBw
21 the directory will be removed when this programs finished.
22 open this link: http://localhost:39062/expr1.html
23 6. Using open link at the 3rd line `http://localhost:39062/expr1.html'
26 1. CFG graph is translated to SVG document, expr1.html embeded them as external
27 document. If you open expr1.html as local file using file:// protocol, some
28 browsers will deny such requests so the web pages will not shown properly.
29 For chrome, you can run it using following command to avoid this:
30 chromium --disable-web-security
31 That's why this program start a localhost http server.
32 2. expr1.html use jquery from http://ajax.googleapis.com, so you need internet
33 access to show the web page.
41 html_template
= string
.Template("""
44 <title>BPF compiler optimization phases for $expr </title>
45 <style type="text/css">
47 /* half width container */
48 display: inline-block;
54 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
55 <!--script type="text/javascript" src="./jquery.min.js"/></script-->
56 <script type="text/javascript">
60 var logs = JSON.parse('$logs');
66 function gurl(index) {
74 return "./expr" + exprid + "_g" + s + ".svg"
77 function annotate_svgs() {
78 if (!leftsvg || !rightsvg) return;
80 $$.each([$$(leftsvg), $$(rightsvg)], function() {
81 $$(this).find("[id|='block'][opacity]").each(function() {
82 $$(this).removeAttr('opacity');
86 $$(leftsvg).find("[id|='block']").each(function() {
87 var has = $$(rightsvg).find("#" + this.id).length != 0;
88 if (!has) $$(this).attr("opacity", "0.4");
90 $$(this).click(function() {
91 var target = $$(rightsvg).find("#" + this.id);
92 var offset = $$("#rightsvgc").offset().top + target.position().top;
93 window.scrollTo(0, offset);
98 $$(rightsvg).find("[id|='block']").each(function() {
99 var has = $$(leftsvg).find("#" + this.id).length != 0;
100 if (!has) $$(this).attr("opacity", "0.4");
102 $$(this).click(function() {
103 var target = $$(leftsvg).find("#" + this.id);
104 var offset = $$("#leftsvgc").offset().top + target.position().top;
105 window.scrollTo(0, offset);
112 function init_svgroot(svg) {
113 svg.setAttribute("width", "100%");
114 svg.setAttribute("height", "100%");
116 function wait_leftsvg() {
118 var doc = document.getElementById("leftsvgc").getSVGDocument();
120 setTimeout(wait_leftsvg, 500);
123 leftsvg = doc.documentElement;
124 //console.log(leftsvg);
126 init_svgroot(leftsvg);
129 function wait_rightsvg() {
130 if (rightsvg) return;
131 var doc = document.getElementById("rightsvgc").getSVGDocument();
133 setTimeout(wait_rightsvg, 500);
136 rightsvg = doc.documentElement;
137 //console.log(rightsvg);
139 init_svgroot(rightsvg);
142 function load_left(index) {
143 var url = gurl(index);
144 var frag = "<embed id='leftsvgc' type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
145 $$("#lsvg").html(frag);
146 $$("#lcomment").html(logs[index]);
147 $$("#lsvglink").attr("href", url);
151 function load_right(index) {
152 var url = gurl(index);
153 var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
154 $$("#rsvg").html(frag);
155 $$("#rcomment").html(logs[index]);
156 $$("#rsvglink").attr("href", url);
161 $$(document).ready(function() {
162 for (var i = 0; i < gcount; i++) {
163 var opt = "<option value='" + i + "'>loop" + i + " -- " + logs[i] + "</option>";
164 $$("#lselect").append(opt);
165 $$("#rselect").append(opt);
167 var on_selected = function() {
168 var index = parseInt($$(this).children("option:selected").val());
169 if (this.id == "lselect")
174 $$("#lselect").change(on_selected);
175 $$("#rselect").change(on_selected);
177 $$("#backward").click(function() {
178 var index = parseInt($$("#lselect option:selected").val());
179 if (index <= 0) return;
180 $$("#lselect").val(index - 1).change();
181 $$("#rselect").val(index).change();
183 $$("#forward").click(function() {
184 var index = parseInt($$("#rselect option:selected").val());
185 if (index >= gcount - 1) return;
186 $$("#lselect").val(index).change();
187 $$("#rselect").val(index + 1).change();
190 if (gcount >= 1) $$("#lselect").val(0).change();
191 if (gcount >= 2) $$("#rselect").val(1).change();
195 <body style="width: 96%">
198 <div style="text-align: center;">
199 <button id="backward" type="button"><<</button>
200
201 <button id="forward" type="button">>></button>
205 <div style="clear: both;">
207 <select id="lselect"></select>
208 <a id="lsvglink" target="_blank">open this svg in browser</a>
209 <p id="lcomment"></p>
212 <select id="rselect"></select>
213 <a id="rsvglink" target="_blank">open this svg in browser</a>
214 <p id="rcomment"></p>
218 <div style="clear: both;">
219 <div id="lsvg" class="hc lc"></div>
220 <div id="rsvg" class="hc rc"></div>
226 def write_html(expr
, gcount
, logs
):
227 logs
= map(lambda s
: s
.strip().replace("\n", "<br/>"), logs
)
230 html
= html_template
.safe_substitute(expr
=expr
.encode("string-escape"), gcount
=gcount
, logs
=json
.dumps(logs
).encode("string-escape"))
231 with
file("expr1.html", "wt") as f
:
234 def render_on_html(infile
):
243 if line
.startswith("machine codes for filter:"):
244 expr
= line
[len("machine codes for filter:"):].strip()
246 elif line
.startswith("digraph BPF {"):
251 if line
.startswith("}"):
257 p
= subprocess
.Popen(['dot', '-Tsvg'], stdin
=subprocess
.PIPE
, stdout
=subprocess
.PIPE
)
258 svg
= p
.communicate(dot
)[0]
259 with
file("expr1_g%03d.svg" % (gid
), "wt") as f
:
269 #unterminated dot graph for expression
272 # BPF parser encounter error(s)
274 write_html(expr
, gid
- 1, logs
)
278 import SimpleHTTPServer
281 class MySocketServer(SocketServer
.TCPServer
):
282 allow_reuse_address
= True
283 Handler
= SimpleHTTPServer
.SimpleHTTPRequestHandler
284 httpd
= MySocketServer(("localhost", 0), Handler
)
285 print "open this link: http://localhost:%d/expr1.html" % (httpd
.server_address
[1])
287 httpd
.serve_forever()
288 except KeyboardInterrupt as e
:
295 os
.chdir(tempfile
.mkdtemp(prefix
="visopts-"))
296 atexit
.register(shutil
.rmtree
, os
.getcwd())
297 print "generated files under directory: %s" % os
.getcwd()
298 print " the directory will be removed when this programs finished."
300 if not render_on_html(sys
.stdin
):
305 if __name__
== "__main__":
306 if '-h' in sys
.argv
or '--help' in sys
.argv
: