2 * Copyright (c) 2016 Mohamed Aslan <maslan@sce.carleton.ca>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36 #include "clustering.h"
39 static struct actl_ctx ctx
;
43 adapt(struct actl_ctx
*c
, double kpi
)
50 put(struct actl_ctx
*c
, const char *key
, const char *val
)
55 phi2rw(c
->target_phi
, c
->conf
->c_nreplicas
, &r
, &w
);
56 (void)clock_gettime(CLOCK_REALTIME
, &ts
);
57 return dht_put_tunable(c
->node
, key
, val
, &ts
, w
);
61 get(struct actl_ctx
*c
, const char *key
, char **val
)
65 phi2rw(c
->target_phi
, c
->conf
->c_nreplicas
, &r
, &w
);
66 return dht_get_tunable(c
->node
, key
, val
, r
);
70 topo(struct actl_ctx
*c
, struct host_info
***hosts
, int *n
)
72 *hosts
= c
->conf
->c_topo
;
73 *n
= c
->conf
->c_topo_n
;
77 init_context(struct actl_ctx
*c
)
81 c
->cntl
= (struct of_controller
*)xmalloc(sizeof(struct of_controller
));
82 c
->node
= (struct dht_node
*)xmalloc(sizeof(struct dht_node
));
83 c
->conf
= (struct config
*)xmalloc(sizeof(struct config
));
91 kmeans_seq_init(&c
->kseq
, 10);
95 load_app(struct actl_ctx
*c
)
99 /* load application */
100 c
->conf
->c_app_so
= dlopen(c
->conf
->c_app_name
, RTLD_NOW
);
101 if (!c
->conf
->c_app_so
)
102 errx(1, "error loading application %s: %s", c
->conf
->c_app_name
, dlerror());
104 c
->conf
->c_app
.a_init
= dlsym(c
->conf
->c_app_so
, "init");
105 if (!(c
->conf
->c_app
.a_init
))
106 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
108 c
->conf
->c_app
.a_main
= dlsym(c
->conf
->c_app_so
, "main");
109 if (!c
->conf
->c_app
.a_main
)
110 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
112 c
->conf
->c_app
.a_handler
= dlsym(c
->conf
->c_app_so
, "handler");
113 if (!c
->conf
->c_app
.a_handler
)
114 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
116 c
->conf
->c_app
.a_kpi
= dlsym(c
->conf
->c_app_so
, "kpi");
117 if (!c
->conf
->c_app
.a_kpi
)
118 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
122 poll_kpi(struct of_controller
*ctl
)
124 double cur_kpi
, cur_phi
;
126 if (ctx
.conf
->c_app_so
&& ctx
.adaptive
) {
127 cur_kpi
= ctx
.conf
->c_app
.a_kpi();
129 kmeans_seq_insert(&ctx
.kseq
, cur_kpi
, ctx
.target_phi
);
130 printf("[INFO] learn KPI = %lf -> Phi = %lf.\n", cur_kpi
, ctx
.target_phi
);
132 cur_phi
= kmeans_seq_find(&ctx
.kseq
, cur_kpi
);
133 printf("[INFO] KPI = (target %lf, current %lf), Phi = %lf.\n", ctx
.target_kpi
, cur_kpi
, cur_phi
);
134 f_log(ctx
.conf
->c_logfp
, "%lf, %lf, %lf, %lf\n", ctx
.target_kpi
, ctx
.target_phi
, cur_kpi
, cur_phi
);
140 learn_timer(struct of_controller
*ctl
)
142 if (ctx
.conf
->c_app_so
&& ctx
.adaptive
&& ctx
.learning
) {
143 ctx
.conf
->c_ltime
-= ctx
.learn_perval
;
144 if (ctx
.conf
->c_ltime
<= 0) {
146 printf("[INFO] learning finished.\n");
147 kmeans_seq_print(&ctx
.kseq
, "LEARN");
149 ctx
.target_phi
+= 0.1;
154 dht_thread(void *arg
)
156 dht_event_loop(ctx
.node
);
161 controller_thread(void *arg
)
163 /* init default app */
164 if (ctx
.conf
->c_app_so
) {
165 optind
= 0; /* make sure apps can use getopt(3) or getopt_long(3) */
166 ctx
.conf
->c_app
.a_init(&ctx
);
167 printf("[INFO] adaptation period is %d sec.\n", ctx
.conf
->c_atime
);
168 ctx
.conf
->c_app
.a_main(ctx
.conf
->c_app_argc
, ctx
.conf
->c_app_argv
);
170 ctx
.learn_perval
= ctx
.conf
->c_ltime
/ 10;
171 ctx
.cntl
->timer(ctx
.cntl
, ctx
.learn_perval
* 1000, learn_timer
);
172 /* poll application-specific KPI */
173 ctx
.cntl
->timer(ctx
.cntl
, ctx
.conf
->c_atime
* 1000, poll_kpi
);
174 ctx
.cntl
->loop(ctx
.cntl
);
179 handler(struct of_controller
*ctl
, struct of_event
*ev
)
182 printf("actl: handler.\n");
184 if (ctx
.conf
->c_app_so
)
185 ctx
.conf
->c_app
.a_handler(ev
);
189 main(int argc
, char **argv
)
191 char *homedir
, *conf_file
;
192 int ch
, flag_altconf
= 0, flag_error
= 0;
193 pthread_t dtid
, ctid
;
196 /* init global context */
199 /* parse command line options */
200 while ((ch
= getopt(argc
, argv
, "c:")) != -1) {
204 conf_file
= strdup(optarg
);
215 return EXIT_FAILURE
; /* TODO: usage */
218 if ((homedir
= getenv("HOME")) == NULL
) {
219 /* TODO: look in current directory */
220 errx(1, "failed to read environmental variable \'$HOME\'");
222 asprintf(&conf_file
, "%s/%s", homedir
, CONFFILENAME
); /* XXX: null */
224 /* parse config file */
225 if (parse_config(ctx
.conf
, conf_file
))
226 errx(1, "error parsing config file.");
229 if (ctx
.conf
->c_logfile
) {
230 ctx
.conf
->c_logfp
= fopen(ctx
.conf
->c_logfile
, "w");
231 if (!ctx
.conf
->c_logfp
)
232 errx(1, "error creating log file.");
235 /* load application */
239 printf("config info...\n");
240 printf("\tnode id \'%s\', control port \'%d\', switch port \'%d\'.\n",
241 ctx
.conf
->c_nodeid
, ctx
.conf
->c_co_port
, ctx
.conf
->c_sw_port
);
242 printf("\topenflow version \'%s\'.\n", ctx
.conf
->c_ofp_verstr
);
243 printf("\tnumber of replicas \'%d\'.\n", ctx
.conf
->c_nreplicas
);
247 if (!dht_init(ctx
.node
, ctx
.conf
->c_nodeid
, ctx
.conf
->c_co_port
, ctx
.conf
->c_nreplicas
, 0, NULL
))
250 printf("dht init successful.\n");
251 pthread_create(&dtid
, NULL
, dht_thread
, NULL
);
253 /* initialize OF controller */
254 if (of_controller_init(ctx
.cntl
, ctx
.conf
->c_sw_port
, ctx
.conf
->c_ofp()))
255 errx(1, "init failed.");
257 printf("controller init successful.\n");
258 ctx
.cntl
->handler(ctx
.cntl
, handler
);
259 pthread_create(&ctid
, NULL
, controller_thread
, NULL
);
262 pthread_join(dtid
, NULL
);
263 pthread_join(ctid
, NULL
);
265 fclose(ctx
.conf
->c_logfp
);