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 init_context(struct actl_ctx
*c
)
74 c
->cntl
= (struct of_controller
*)xmalloc(sizeof(struct of_controller
));
75 c
->node
= (struct dht_node
*)xmalloc(sizeof(struct dht_node
));
76 c
->conf
= (struct config
*)xmalloc(sizeof(struct config
));
83 kmeans_seq_init(&c
->kseq
, 10);
87 load_app(struct actl_ctx
*c
)
91 /* load application */
92 c
->conf
->c_app_so
= dlopen(c
->conf
->c_app_name
, RTLD_NOW
);
93 if (!c
->conf
->c_app_so
)
94 errx(1, "error loading application %s: %s", c
->conf
->c_app_name
, dlerror());
96 c
->conf
->c_app
.a_init
= dlsym(c
->conf
->c_app_so
, "init");
97 if (!(c
->conf
->c_app
.a_init
))
98 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
100 c
->conf
->c_app
.a_main
= dlsym(c
->conf
->c_app_so
, "main");
101 if (!c
->conf
->c_app
.a_main
)
102 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
104 c
->conf
->c_app
.a_handler
= dlsym(c
->conf
->c_app_so
, "handler");
105 if (!c
->conf
->c_app
.a_handler
)
106 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
108 c
->conf
->c_app
.a_kpi
= dlsym(c
->conf
->c_app_so
, "kpi");
109 if (!c
->conf
->c_app
.a_kpi
)
110 errx(1, "error loading symbol from %s: %s", c
->conf
->c_app_name
, dlerror());
114 poll_kpi(struct of_controller
*ctl
)
116 double cur_kpi
, cur_phi
;
118 if (ctx
.conf
->c_app_so
&& ctx
.adaptive
) {
119 cur_kpi
= ctx
.conf
->c_app
.a_kpi();
121 kmeans_seq_insert(&ctx
.kseq
, cur_kpi
, ctx
.target_phi
);
122 printf("[INFO] learn KPI = %lf -> Phi = %lf.\n", cur_kpi
, ctx
.target_phi
);
124 cur_phi
= kmeans_seq_find(&ctx
.kseq
, cur_kpi
);
125 printf("[INFO] KPI = (target %lf, current %lf), Phi = %lf.\n", ctx
.target_kpi
, cur_kpi
, cur_phi
);
126 f_log(ctx
.conf
->c_logfp
, "%lf, %lf, %lf, %lf\n", ctx
.target_kpi
, ctx
.target_phi
, cur_kpi
, cur_phi
);
132 learn_timer(struct of_controller
*ctl
)
134 if (ctx
.conf
->c_app_so
&& ctx
.adaptive
&& ctx
.learning
) {
135 ctx
.conf
->c_ltime
-= ctx
.learn_perval
;
136 if (ctx
.conf
->c_ltime
<= 0) {
138 printf("[INFO] learning finished.\n");
139 kmeans_seq_print(&ctx
.kseq
, "LEARN");
141 ctx
.target_phi
+= 0.1;
146 dht_thread(void *arg
)
148 dht_event_loop(ctx
.node
);
153 controller_thread(void *arg
)
155 /* init default app */
156 if (ctx
.conf
->c_app_so
) {
157 optind
= 0; /* make sure apps can use getopt(3) or getopt_long(3) */
158 ctx
.conf
->c_app
.a_init(&ctx
);
159 printf("[INFO] adaptation period is %d sec.\n", ctx
.conf
->c_atime
);
160 ctx
.conf
->c_app
.a_main(ctx
.conf
->c_app_argc
, ctx
.conf
->c_app_argv
);
162 ctx
.learn_perval
= ctx
.conf
->c_ltime
/ 10;
163 ctx
.cntl
->timer(ctx
.cntl
, ctx
.learn_perval
* 1000, learn_timer
);
164 /* poll application-specific KPI */
165 ctx
.cntl
->timer(ctx
.cntl
, ctx
.conf
->c_atime
* 1000, poll_kpi
);
166 ctx
.cntl
->loop(ctx
.cntl
);
171 handler(struct of_controller
*ctl
, struct of_event
*ev
)
174 printf("actl: handler.\n");
176 if (ctx
.conf
->c_app_so
)
177 ctx
.conf
->c_app
.a_handler(ev
);
181 main(int argc
, char **argv
)
183 char *homedir
, *conf_file
;
184 int ch
, flag_altconf
= 0, flag_error
= 0;
185 pthread_t dtid
, ctid
;
188 /* init global context */
191 /* parse command line options */
192 while ((ch
= getopt(argc
, argv
, "c:")) != -1) {
196 conf_file
= strdup(optarg
);
207 return EXIT_FAILURE
; /* TODO: usage */
210 if ((homedir
= getenv("HOME")) == NULL
) {
211 /* TODO: look in current directory */
212 errx(1, "failed to read environmental variable \'$HOME\'");
214 asprintf(&conf_file
, "%s/%s", homedir
, CONFFILENAME
); /* XXX: null */
216 /* parse config file */
217 if (parse_config(ctx
.conf
, conf_file
))
218 errx(1, "error parsing config file.");
221 if (ctx
.conf
->c_logfile
) {
222 ctx
.conf
->c_logfp
= fopen(ctx
.conf
->c_logfile
, "w");
223 if (!ctx
.conf
->c_logfp
)
224 errx(1, "error creating log file.");
227 /* load application */
231 printf("config info...\n");
232 printf("\tnode id \'%s\', control port \'%d\', switch port \'%d\'.\n",
233 ctx
.conf
->c_nodeid
, ctx
.conf
->c_co_port
, ctx
.conf
->c_sw_port
);
234 printf("\topenflow version \'%s\'.\n", ctx
.conf
->c_ofp_verstr
);
235 printf("\tnumber of replicas \'%d\'.\n", ctx
.conf
->c_nreplicas
);
239 if (!dht_init(ctx
.node
, ctx
.conf
->c_nodeid
, ctx
.conf
->c_co_port
, ctx
.conf
->c_nreplicas
, 0, NULL
))
242 printf("dht init successful.\n");
243 pthread_create(&dtid
, NULL
, dht_thread
, NULL
);
245 /* initialize OF controller */
246 if (of_controller_init(ctx
.cntl
, ctx
.conf
->c_sw_port
, ctx
.conf
->c_ofp()))
247 errx(1, "init failed.");
249 printf("controller init successful.\n");
250 ctx
.cntl
->handler(ctx
.cntl
, handler
);
251 pthread_create(&ctid
, NULL
, controller_thread
, NULL
);
254 pthread_join(dtid
, NULL
);
255 pthread_join(ctid
, NULL
);
257 fclose(ctx
.conf
->c_logfp
);