1 #include <nm_core.h>
2 #include <nm_utils.h>
3 #include <nm_string.h>
4 #include <nm_vector.h>
5 #include <nm_network.h>
6 #include <nm_svg_map.h>
7 #include <nm_database.h>
8 #include <nm_lan_settings.h>
9
10 #if defined (NM_WITH_NETWORK_MAP)
11 #include <gvc.h>
12
13 static char NM_EMPTY_STR[] = "";
14 static char NM_GV_LABEL[] = "label";
15 static char NM_GV_STYLE[] = "style";
16 static char NM_GV_SHAPE[] = "shape";
17 static char NM_GV_FILL[] = "filled";
18 static char NM_GV_FCOL[] = "fillcolor";
19 static char NM_GV_RECT[] = "rect";
20 static char NM_GV_SVG[] = "svg";
21 static char NM_VM_COLOR[] = "#4fbcdd";
22 static char NM_VE_COLOR[] = "#59e088";
23
24 typedef Agraph_t nm_gvgraph_t;
25 typedef Agnode_t nm_gvnode_t;
26 typedef Agedge_t nm_gvedge_t;
27 typedef GVC_t nm_gvctx_t;
28
nm_svg_map(const char * path,const nm_vect_t * veths,int state,const nm_str_t * layout,const nm_str_t * group)29 void nm_svg_map(const char *path, const nm_vect_t *veths,
30 int state, const nm_str_t *layout, const nm_str_t *group)
31 {
32 nm_gvctx_t *gvc;
33 nm_gvgraph_t *graph;
34
35 if ((gvc = gvContext()) == NULL)
36 nm_bug(_("%s: cannot create graphviz ctx"), __func__);
37
38 graph = agopen("network_map", Agundirected, NULL);
39 agattr(graph, AGRAPH, "overlap", "scalexy");
40 agattr(graph, AGRAPH, "splines", "true");
41 agattr(graph, AGRAPH, "sep", "+25,25");
42
43 //@TODO Some of variables may be moved outside, and freed only once
44 for (size_t v = 0; v < veths->n_memb; v++) {
45 nm_vect_t vms = NM_INIT_VECT;
46 nm_str_t lname = NM_INIT_STR;
47 nm_str_t rname = NM_INIT_STR;
48 nm_str_t query = NM_INIT_STR;
49 nm_gvnode_t *vnode;
50 size_t vms_count;
51
52 nm_lan_parse_name(nm_vect_str(veths, v), &lname, &rname);
53
54 if (!group->len) {
55 switch (state) {
56 case NM_SVG_STATE_UP:
57 if (nm_net_link_status(&lname) != NM_OK)
58 goto next;
59 break;
60 case NM_SVG_STATE_DOWN:
61 if (nm_net_link_status(&lname) == NM_OK)
62 goto next;
63 break;
64 default:
65 break;
66 }
67 }
68
69 if (group->len) {
70 nm_str_format(&query, NM_GET_IFMAPGR_SQL, group->data, lname.data, rname.data);
71 } else {
72 nm_str_format(&query, NM_GET_IFMAP_SQL, lname.data, rname.data);
73 }
74 nm_db_select(query.data, &vms);
75
76 if (group->len && !vms.n_memb) {
77 goto next;
78 }
79
80 vnode = agnode(graph, nm_vect_str_ctx(veths, v), NM_TRUE);
81 agsafeset(vnode, NM_GV_STYLE, NM_GV_FILL, NM_EMPTY_STR);
82 agsafeset(vnode, NM_GV_FCOL, NM_VE_COLOR, NM_EMPTY_STR);
83 agsafeset(vnode, NM_GV_SHAPE, NM_GV_RECT, NM_EMPTY_STR);
84
85 vms_count = vms.n_memb / 2;
86 for (size_t n = 0; n < vms_count; n++) {
87 size_t idx_shift = 2 * n;
88 nm_gvnode_t *node = agnode(graph, nm_vect_str_ctx(&vms, idx_shift), NM_TRUE);
89 nm_gvedge_t *edge = agedge(graph, node, vnode, NULL, NM_TRUE);
90
91 agsafeset(edge, NM_GV_LABEL, nm_vect_str_ctx(&vms, idx_shift + 1), NM_EMPTY_STR);
92 agsafeset(node, NM_GV_STYLE, NM_GV_FILL, NM_EMPTY_STR);
93 agsafeset(node, NM_GV_FCOL, NM_VM_COLOR, NM_EMPTY_STR);
94 }
95
96 nm_vect_free(&vms, nm_str_vect_free_cb);
97 nm_str_free(&query);
98 next:
99 nm_str_free(&lname);
100 nm_str_free(&rname);
101 }
102
103 gvLayout(gvc, graph, layout->data);
104 gvRenderFilename(gvc, graph, NM_GV_SVG, path);
105
106 gvFreeLayout(gvc, graph);
107 agclose(graph);
108 gvFreeContext(gvc);
109 }
110 #endif /* NM_WITH_NETWORK_MAP */
111 /* vim:set ts=4 sw=4: */
112