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.
24 #include <sys/queue.h>
25 #include <arpa/inet.h>
31 SIMPLEQ_HEAD
(list
, list_item
);
34 SIMPLEQ_ENTRY
(list_item
) next
;
40 extern
int yylex(void);
42 int yyerror(const char *, ...
);
43 static ofp_fptr check_ofp_version
(const char *);
44 static char *filename
;
45 static struct config
*conf
;
56 %token PEERS CONTROLLER
59 %token OPENFLOW VERSION
61 %token ADAPT EVERY SEC MIN
62 %token LEARN USING WITH FOR EQUAL
63 %token KMEANSSEQ CLUSTERS
64 %token KMEANSINCR THRESHOLD
66 %token TOPOLOGY HOST AT DPID
67 %token COMMA LCBRACKET RCBRACKET
95 conf
->c_nodeid
= strdup
($2);
99 listen
: LISTEN ON PORT NUMBER
{
100 conf
->c_co_port
= $4;
104 peer_list
: CONTROLLER STRING IP STRING PORT NUMBER
{
105 struct peer
*p
= (struct peer
*)malloc
(sizeof
(struct peer
));
106 struct list_item
*q
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
108 p
->node_id
= strdup
($2);
109 if
(!inet_aton
($4, &p
->ip_addr
))
110 errx
(1, "invalid IP address");
114 $$
= (struct list
*)malloc
(sizeof
(struct list
));
116 SIMPLEQ_INSERT_TAIL
($$
, q
, next
);
118 | peer_list COMMA CONTROLLER STRING IP STRING PORT NUMBER
{
119 struct peer
*p
= (struct peer
*)malloc
(sizeof
(struct peer
));
120 struct list_item
*q
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
122 p
->node_id
= strdup
($4);
123 if
(!inet_aton
($6, &p
->ip_addr
))
124 errx
(1, "invalid IP address");
128 SIMPLEQ_INSERT_TAIL
($1, q
, next
);
132 peers
: PEERS LCBRACKET peer_list RCBRACKET
{
136 SIMPLEQ_FOREACH
(p
, $3, next
)
139 conf
->c_peers
= (struct peer
*)reallocarray
(NULL
, n
, sizeof
(struct peer
));
140 while
(!SIMPLEQ_EMPTY
($3)) {
141 p
= SIMPLEQ_FIRST
($3);
142 conf
->c_peers
[i
++] = *((struct peer
*)p
->val
);
143 SIMPLEQ_REMOVE_HEAD
($3, next
);
150 replicas
: REPLICAS NUMBER
{
151 conf
->c_nreplicas
= $2;
155 openflow
: OPENFLOW VERSION STRING
{
156 if
((conf
->c_ofp
= check_ofp_version
($3)) == NULL
) {
157 yyerror("OpenFlow version '%s' not supported.", $3);
160 conf
->c_ofp_verstr
= strdup
($3);
162 | OPENFLOW LISTEN ON PORT NUMBER
{
163 conf
->c_sw_port
= $5;
168 struct list_item
*s
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
171 $$
= (struct list
*)malloc
(sizeof
(struct list
));
173 SIMPLEQ_INSERT_TAIL
($$
, s
, next
);
175 | str_list COMMA STRING
{
176 struct list_item
*s
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
179 SIMPLEQ_INSERT_TAIL
($1, s
, next
);
183 param_list
: VAR STRING
{
184 struct list_item
*p
, *q
;
186 p
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
187 q
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
188 asprintf
((char **)&p
->val
, "--%s", $1);
190 $$
= (struct list
*)malloc
(sizeof
(struct list
));
192 SIMPLEQ_INSERT_TAIL
($$
, p
, next
);
193 SIMPLEQ_INSERT_TAIL
($$
, q
, next
);
195 | param_list COMMA VAR STRING
{
196 struct list_item
*p
, *q
;
198 p
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
199 q
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
200 asprintf
((char **)&p
->val
, "--%s", $3);
202 SIMPLEQ_INSERT_TAIL
($1, p
, next
);
203 SIMPLEQ_INSERT_TAIL
($1, q
, next
);
205 | param_list COMMA VAR LCBRACKET str_list RCBRACKET
{
206 struct list_item
*p
, *q
;
208 while
(!SIMPLEQ_EMPTY
($5)) {
209 p
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
210 asprintf
((char **)&p
->val
, "--%s", $3);
211 SIMPLEQ_INSERT_TAIL
($1, p
, next
);
212 q
= SIMPLEQ_FIRST
($5);
213 SIMPLEQ_REMOVE_HEAD
($5, next
);
214 SIMPLEQ_INSERT_TAIL
($1, q
, next
);
219 application
: APPLICATION STRING
{
220 conf
->c_app_name
= strdup
($2);
222 | APPLICATION STRING LCBRACKET param_list RCBRACKET
{
228 conf
->c_app_name
= strdup
($2);
229 SIMPLEQ_FOREACH
(p
, $4, next
)
232 argv
= (char **)reallocarray
(NULL
, argc
, sizeof
(char *));
233 argv
[0] = strdup
($2);
234 while
(!SIMPLEQ_EMPTY
($4)) {
235 p
= SIMPLEQ_FIRST
($4);
236 argv
[++i
] = (char *)p
->val
;
237 SIMPLEQ_REMOVE_HEAD
($4, next
);
240 conf
->c_app_argc
= argc
;
241 conf
->c_app_argv
= argv
;
246 adapt
: ADAPT EVERY NUMBER SEC
{
248 yyerror("adaptation time must be > 1.");
253 | ADAPT EVERY NUMBER MIN
{
255 yyerror("adaptation time must be > 1.");
258 conf
->c_atime
= $3 * 60;
262 learn
: LEARN USING KMEANSSEQ WITH CLUSTERS EQUAL NUMBER FOR NUMBER SEC
{
264 yyerror("learning time must be >= 30 sec.");
268 conf
->c_lalgo
= LEARN_KMEANS_SEQ
;
271 | LEARN USING KMEANSSEQ WITH CLUSTERS EQUAL NUMBER FOR NUMBER MIN
{
273 yyerror("use you may use seconds for learning time.");
276 conf
->c_ltime
= $9 * 60;
277 conf
->c_lalgo
= LEARN_KMEANS_SEQ
;
280 | LEARN USING KMEANSINCR WITH THRESHOLD EQUAL NUMBER FOR NUMBER SEC
{
282 yyerror("learning time must be >= 30 sec.");
286 conf
->c_lalgo
= LEARN_KMEANS_INCR
;
289 | LEARN USING KMEANSINCR WITH THRESHOLD EQUAL NUMBER FOR NUMBER MIN
{
291 yyerror("use you may use seconds for learning time.");
294 conf
->c_ltime
= $9 * 60;
295 conf
->c_lalgo
= LEARN_KMEANS_INCR
;
300 log
: LOG TO STRING
{
301 conf
->c_logfile
= strdup
($3);
305 host_list
: HOST STRING AT DPID STRING PORT NUMBER
{
306 struct host_info
*h
= (struct host_info
*)malloc
(sizeof
(struct host_info
));
307 struct list_item
*p
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
309 if
(!inet_aton
($2, &h
->ip_addr
))
310 errx
(1, "invalid IP address");
311 if
(!(h
->dpid
= dpid_aton
($5)))
312 errx
(1, "invalid DPID");
316 $$
= (struct list
*)malloc
(sizeof
(struct list
));
318 SIMPLEQ_INSERT_TAIL
($$
, p
, next
);
320 | host_list COMMA HOST STRING AT DPID STRING PORT NUMBER
{
321 struct host_info
*h
= (struct host_info
*)malloc
(sizeof
(struct host_info
));
322 struct list_item
*p
= (struct list_item
*)malloc
(sizeof
(struct list_item
));
324 if
(!inet_aton
($4, &h
->ip_addr
))
325 errx
(1, "invalid IP address");
326 if
(!(h
->dpid
= dpid_aton
($7)))
327 errx
(1, "invalid DPID");
331 SIMPLEQ_INSERT_TAIL
($1, p
, next
);
335 topology
: TOPOLOGY LCBRACKET host_list RCBRACKET
{
337 struct host_info
**hosts
;
340 SIMPLEQ_FOREACH
(p
, $3, next
)
342 hosts
= (struct host_info
**)reallocarray
(NULL
, n
, sizeof
(struct host_info
*));
343 while
(!SIMPLEQ_EMPTY
($3)) {
344 p
= SIMPLEQ_FIRST
($3);
345 hosts
[i
++] = (struct host_info
*)p
->val
;
346 SIMPLEQ_REMOVE_HEAD
($3, next
);
350 conf
->c_topo
= hosts
;
357 check_ofp_version
(const char *ver
)
361 for
(i
= 0 ; i
< N_OFP_VERS
; i
++)
362 if
(!strcmp
(ver
, ofp_vers
[i
].ver
))
363 return ofp_vers
[i
].func
;
368 yyerror(const char *fmt
, ...
)
373 fprintf
(stdout
, "%s:%d: ", filename
, yylineno
);
374 vfprintf
(stdout
, fmt
, ap
);
375 fprintf
(stdout
, "\n");
382 parse_config
(struct config
*c
, const char *file
)
387 errx
(1, "parse_config");
388 if
((yyin
= fopen
(file
, "r")) == NULL
) {
389 errx
(1, "failed to load config file");
391 filename
= strdup
(file
);
393 conf
->c_app_name
= NULL
;
394 conf
->c_logfile
= NULL
;