use %016llx when printing dpids
[actl.git] / parse.y
blob5295a134381210c3f71e4c49fd11524ba41b001d
1 /*
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.
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <err.h>
23 #include <errno.h>
24 #include <sys/queue.h>
25 #include <arpa/inet.h>
27 #include "conf.h"
28 #include "utils.h"
30 /* types */
31 SIMPLEQ_HEAD(list, list_item);
32 struct list_item {
33 void *val;
34 SIMPLEQ_ENTRY(list_item) next;
37 /* lex vars */
38 extern FILE *yyin;
39 extern int yylineno;
40 extern int yylex(void);
41 /* global vars */
42 int yyerror(const char *, ...);
43 static ofp_fptr check_ofp_version(const char *);
44 static char *filename;
45 static struct config *conf;
48 %union {
49 int i;
50 char *s;
51 struct list *l;
52 struct host_info *h;
55 %token ID
56 %token LISTEN ON
57 %token CONTROLLER
58 %token IP PORT
59 %token REPLICAS
60 %token OPENFLOW VERSION
61 %token APPLICATION
62 %token ADAPT EVERY SEC MIN
63 %token LEARN FOR
64 %token LOG TO
65 %token TOPOLOGY HOST AT DPID
66 %token COMMA LCBRACKET RCBRACKET
68 %token<i> BOOL
69 %token<i> NUMBER
70 %token<s> VAR
71 %token<s> STRING
73 %type<l> str_list
74 %type<l> param_list
75 %type<l> host_list
79 main :
80 | main id
81 | main listen
82 | main controller
83 | main replicas
84 | main openflow
85 | main application
86 | main adapt
87 | main learn
88 | main log
89 | main topology
92 id : ID STRING {
93 conf->c_nodeid = strdup($2);
97 listen : LISTEN ON PORT NUMBER {
98 conf->c_co_port = $4;
102 controller : CONTROLLER STRING IP STRING PORT NUMBER {
103 //printf("CONTROLLER: %s, ip addr=%s, port=%d\n", $2, $4, $6);
105 | CONTROLLER STRING IP STRING {
106 //printf("CONTROLLER: %s, ip addr=%s\n", $2, $4);
110 replicas : REPLICAS NUMBER {
111 conf->c_nreplicas = $2;
115 openflow : OPENFLOW VERSION STRING {
116 if ((conf->c_ofp = check_ofp_version($3)) == NULL) {
117 yyerror("OpenFlow version '%s' not supported.", $3);
118 YYABORT;
120 conf->c_ofp_verstr = strdup($3);
122 | OPENFLOW LISTEN ON PORT NUMBER {
123 conf->c_sw_port = $5;
127 str_list : STRING {
128 struct list_item *s = (struct list_item *)malloc(sizeof(struct list_item));
130 s->val = strdup($1);
131 SIMPLEQ_INIT($$);
132 SIMPLEQ_INSERT_TAIL($$, s, next);
134 | str_list COMMA STRING {
135 struct list_item *s = (struct list_item *)malloc(sizeof(struct list_item));
137 s->val = strdup($3);
138 SIMPLEQ_INSERT_TAIL($1, s, next);
142 param_list : VAR STRING {
143 struct list_item *p, *q;
145 p = (struct list_item *)malloc(sizeof(struct list_item));
146 q = (struct list_item *)malloc(sizeof(struct list_item));
147 asprintf((char **)&p->val, "--%s", $1);
148 q->val = strdup($2);
149 SIMPLEQ_INIT($$);
150 SIMPLEQ_INSERT_TAIL($$, p, next);
151 SIMPLEQ_INSERT_TAIL($$, q, next);
153 | param_list COMMA VAR STRING {
154 struct list_item *p, *q;
156 p = (struct list_item *)malloc(sizeof(struct list_item));
157 q = (struct list_item *)malloc(sizeof(struct list_item));
158 asprintf((char **)&p->val, "--%s", $3);
159 q->val = strdup($4);
160 SIMPLEQ_INSERT_TAIL($1, p, next);
161 SIMPLEQ_INSERT_TAIL($1, q, next);
163 | param_list COMMA VAR LCBRACKET str_list RCBRACKET {
164 struct list_item *p, *q;
166 while (!SIMPLEQ_EMPTY($5)) {
167 p = (struct list_item *)malloc(sizeof(struct list_item));
168 asprintf((char **)&p->val, "--%s", $3);
169 SIMPLEQ_INSERT_TAIL($1, p, next);
170 q = SIMPLEQ_FIRST($5);
171 SIMPLEQ_REMOVE_HEAD($5, next);
172 SIMPLEQ_INSERT_TAIL($1, q, next);
177 application : APPLICATION STRING {
178 conf->c_app_name = strdup($2);
180 | APPLICATION STRING LCBRACKET param_list RCBRACKET {
181 int i = 0;
182 int argc = 0;
183 char **argv;
184 struct list_item *p;
186 conf->c_app_name = strdup($2);
187 SIMPLEQ_FOREACH(p, $4, next)
188 ++argc;
189 ++argc;
190 argv = (char **)reallocarray(NULL, argc, sizeof(char *));
191 argv[0] = strdup($2);
192 while (!SIMPLEQ_EMPTY($4)) {
193 p = SIMPLEQ_FIRST($4);
194 argv[++i] = p->val;
195 SIMPLEQ_REMOVE_HEAD($4, next);
196 free(p);
198 conf->c_app_argc = argc;
199 conf->c_app_argv = argv;
203 adapt : ADAPT EVERY NUMBER SEC {
204 if ($3 < 1) {
205 yyerror("adaptation time must be > 1.");
206 YYABORT;
208 conf->c_atime = $3;
210 | ADAPT EVERY NUMBER MIN {
211 if ($3 < 1) {
212 yyerror("adaptation time must be > 1.");
213 YYABORT;
215 conf->c_atime = $3 * 60;
219 learn : LEARN FOR NUMBER SEC {
220 if ($3 < 30) {
221 yyerror("learning time must be >= 30 sec.");
222 YYABORT;
224 conf->c_ltime = $3;
226 | LEARN FOR NUMBER MIN {
227 if ($3 < 1) {
228 yyerror("use you may use seconds for learning time.");
229 YYABORT;
231 conf->c_ltime = $3 * 60;
235 log : LOG TO STRING {
236 conf->c_logfile = strdup($3);
240 host_list : HOST STRING AT DPID STRING PORT NUMBER {
241 struct host_info *h = (struct host_info *)malloc(sizeof(struct host_info));
242 struct list_item *p = (struct list_item *)malloc(sizeof(struct list_item));
244 if (!inet_aton($2, &h->ip_addr))
245 errx(1, "invalid IP address");
246 if (!(h->dpid = dpid_aton($5)))
247 errx(1, "invalid DPID");
248 h->port = $7;
250 p->val = h;
251 SIMPLEQ_INIT($$);
252 SIMPLEQ_INSERT_TAIL($$, p, next);
254 | host_list COMMA HOST STRING AT DPID STRING PORT NUMBER {
255 struct host_info *h = (struct host_info *)malloc(sizeof(struct host_info));
256 struct list_item *p = (struct list_item *)malloc(sizeof(struct list_item));
258 if (!inet_aton($4, &h->ip_addr))
259 errx(1, "invalid IP address");
260 if (!(h->dpid = dpid_aton($7)))
261 errx(1, "invalid DPID");
262 h->port = $9;
264 p->val = h;
265 SIMPLEQ_INSERT_TAIL($1, p, next);
269 topology : TOPOLOGY LCBRACKET host_list RCBRACKET {
270 int i = 0, n = 0;
271 struct host_info **hosts;
272 struct list_item *p;
274 SIMPLEQ_FOREACH(p, $3, next)
275 ++n;
276 hosts = (struct host_info **)reallocarray(NULL, n, sizeof(struct host_info *));
277 while (!SIMPLEQ_EMPTY($3)) {
278 p = SIMPLEQ_FIRST($3);
279 hosts[i++] = (struct host_info *)p->val;
280 SIMPLEQ_REMOVE_HEAD($3, next);
281 free(p);
283 conf->c_topo_n = n;
284 conf->c_topo = hosts;
289 static ofp_fptr
290 check_ofp_version(const char *ver)
292 int i;
294 for (i = 0 ; i < N_OFP_VERS ; i++)
295 if (!strcmp(ver, ofp_vers[i].ver))
296 return ofp_vers[i].func;
297 return NULL;
301 yyerror(const char *fmt, ...)
303 va_list ap;
305 va_start(ap, fmt);
306 fprintf(stdout, "%s:%d: ", filename, yylineno);
307 vfprintf(stdout, fmt, ap);
308 fprintf(stdout, "\n");
309 va_end(ap);
311 return 0;
315 parse_config(struct config *c, const char *file)
317 int ret;
319 if (c == NULL)
320 errx(1, "parse_config");
321 if ((yyin = fopen(file, "r")) == NULL) {
322 errx(1, "failed to load config file");
324 filename = strdup(file);
325 conf = c;
326 conf->c_app_name = NULL;
327 conf->c_logfile = NULL;
328 ret = yyparse();
329 fclose(yyin);
331 return ret;