xref: /mOS-networking-stack/core/src/config.c (revision 8a941c7e)
1 #include <stdlib.h>
2 #include <assert.h>
3 #include <sys/socket.h>
4 #include <sys/ioctl.h>
5 #include <sys/stat.h>
6 #include <net/if.h>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 #include <netdb.h>
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include "mtcp.h"
16 #include "config.h"
17 #include "tcp_in.h"
18 #include "arp.h"
19 #include "debug.h"
20 #include "mtcp_util.h"
21 /* for setting up io modules */
22 #include "io_module.h"
23 /* for if_nametoindex */
24 #include <net/if.h>
25 
26 #define MAX_PROCLINE_LEN 1024
27 
28 #ifdef DARWIN
29 #pragma GCC diagnostic ignored "-Wformat"
30 #pragma GCC diagnostic ignored "-Wempty-body"
31 #endif
32 
33 /*----------------------------------------------------------------------------*/
34 int8_t end_app_exists = 0;
35 int8_t mon_app_exists = 0;
36 addr_pool_t ap[ETH_NUM] = {NULL};
37 char *file = NULL;
38 /*----------------------------------------------------------------------------*/
39 /* return 0 on failure */
40 #define MATCH_ITEM(name, item) \
41 	((strncmp(#name, item, strlen(#name)) == 0) \
42 	 && (!isalnum(item[strlen(#name)])))
43 
44 #define TRY_ASSIGN_NUM(name, base, item, value) \
45 	((strncmp(#name, item, strlen(#name)) == 0) \
46 	 && (!isalnum(item[strlen(#name)])) \
47 	 && (sscanf(value, \
48 			(sizeof((base)->name) == sizeof(char)) ? "%hhi" : \
49 			(sizeof((base)->name) == sizeof(short)) ? "%hi" : \
50 			(sizeof((base)->name) == sizeof(int)) ? "%i" : \
51 			(sizeof((base)->name) == sizeof(long)) ? "%li" : \
52 			(sizeof((base)->name) == sizeof(long long)) ? "%lli" : "ERROR", \
53 			    &(base)->name) > 0))
54 
55 #define TRY_ASSIGN_STR(name, base, item, value) \
56 	(((strncmp(#name, item, strlen(#name)) == 0) \
57 	  && (!isalnum(item[strlen(#name)])) \
58 	  && (strlen(value) < sizeof((base)->name))) ? \
59 	 (strcpy((base)->name, value), 1) : 0)
60 
61 #define LINE_FOREACH(line, llen, buf, blen) \
62 	for(line = buf, \
63 		llen = ((strchr(line, '\n') == NULL) ? (buf + blen - line) \
64 											 : strchr(line, '\n') - line); \
65 		line + llen < buf + blen; \
66 		line += llen + 1, \
67 		llen = ((strchr(line, '\n') == NULL) ? (buf + blen - line) \
68 											 : strchr(line, '\n') - line)) \
69 /*----------------------------------------------------------------------------*/
70 static int
71 SetMultiProcessSupport(char *multiprocess_details)
72 {
73 	char *token = " =";
74 	char *sample;
75 	char *saveptr;
76 
77 	TRACE_CONFIG("Loading multi-process configuration\n");
78 
79 	sample = strtok_r(multiprocess_details, token, &saveptr);
80 	if (sample == NULL) {
81 		TRACE_CONFIG("No option for multi-process support given!\n");
82 		return -1;
83 	}
84 	g_config.mos->multiprocess_curr_core = atoi(sample);
85 
86 	sample = strtok_r(NULL, token, &saveptr);
87 	if (sample != NULL && !strcmp(sample, "master"))
88 		g_config.mos->multiprocess_is_master = 1;
89 
90 	return 0;
91 }
92 /*----------------------------------------------------------------------------*/
93 static int
94 DetectWord(char *buf, int len, char **word, int *wlen)
95 {
96 	int i;
97 	for (i = 0; i < len; i++) {
98 		if (isspace(buf[i]))
99 			continue;
100 
101 		if (isalpha(buf[i])) {
102 			*word = &buf[i];
103 			break;
104 		} else
105 			/* not word */
106 			return -1;
107 	}
108 
109 	if (i == len)
110 		return -1;
111 
112 	for (*wlen = 0; *wlen < len; (*wlen)++) {
113 		if (isalnum((*word)[*wlen]) || (*word)[*wlen] == '_')
114 			continue;
115 
116 		assert(*wlen != 0);
117 		break;
118 	}
119 
120 	assert(*word >= buf && *word + *wlen <= buf + len);
121 
122 	return 0;
123 }
124 /*----------------------------------------------------------------------------*/
125 static int
126 ReadItemValue(char *line, int llen, char *item, int ilen, char *value, int vlen)
127 {
128 	const char *end = &line[llen];
129 	char *word = NULL;
130 	int wlen = 0;
131 
132 	if (DetectWord(line, llen, &word, &wlen) < 0 || wlen > ilen)
133 		return -1;
134 
135 	line = word + wlen;
136 
137 	/* skip space */
138 	while (line < end && isspace(*line))
139 		line++;
140 
141 	if (*(line++) != '=')
142 		return -1;
143 
144 	while (line < end && isspace(*line))
145 		line++;
146 
147 	if (end - line > vlen)
148 		return -1;
149 
150 	while (isspace(*(end - 1)))
151 		end--;
152 
153 	if (end <= line)
154 		return -1;
155 
156 	strncpy(item, word, wlen);
157 
158 	strncpy(value, line, (size_t)(end - line));
159 
160 	return 0;
161 }
162 /*----------------------------------------------------------------------------*/
163 static void
164 FeedAppConfLine(struct conf_block *blk, char *line, int len)
165 {
166 	struct app_conf * const conf = (struct app_conf *)blk->conf;
167 
168 	char item[WORD_LEN + 1] = {0};
169 	char value[STR_LEN + 1] = {0};
170 
171 	if (ReadItemValue(line, len, item, WORD_LEN, value, STR_LEN) < 0)
172 		return;
173 
174 	if      (TRY_ASSIGN_STR(type,       conf, item, value));
175 	else if (TRY_ASSIGN_STR(run,        conf, item, value)) {
176 		StrToArgs(conf->run, &conf->app_argc, conf->app_argv, MOS_APP_ARGC);
177 #if 0
178 		conf->app_argv[conf->app_argc++] = strtok(conf->run, " \t\n\r");
179 		while (conf->app_argc < MOS_APP_ARGC &&
180 				(conf->app_argv[conf->app_argc] = strtok(NULL, " \t\n\r")))
181 			conf->app_argc++;
182 #endif
183 	} else if (TRY_ASSIGN_NUM(cpu_mask,   conf, item, value));
184 	else if (TRY_ASSIGN_NUM(ip_forward, conf, item, value));
185 }
186 /*----------------------------------------------------------------------------*/
187 static void
188 FeedMosConfLine(struct conf_block *blk, char *line, int len)
189 {
190 	struct mos_conf * const conf = (struct mos_conf *)blk->conf;
191 
192 	char item[WORD_LEN + 1] = {0};
193 	char value[STR_LEN + 1] = {0};
194 
195 	if (ReadItemValue(line, len, item, WORD_LEN, value, STR_LEN) < 0)
196 		return;
197 
198 	if (TRY_ASSIGN_NUM(nb_mem_channels, conf, item, value));
199 	else if (TRY_ASSIGN_NUM(forward,         conf, item, value));
200 	else if (TRY_ASSIGN_NUM(max_concurrency, conf, item, value));
201 	else if (TRY_ASSIGN_NUM(rmem_size,       conf, item, value));
202 	else if (TRY_ASSIGN_NUM(wmem_size,       conf, item, value));
203 	else if (TRY_ASSIGN_NUM(tcp_tw_interval, conf, item, value))
204 		g_config.mos->tcp_tw_interval =
205 			SEC_TO_USEC(g_config.mos->tcp_tw_interval) / TIME_TICK;
206 	else if (TRY_ASSIGN_NUM(tcp_timeout,     conf, item, value))
207 		g_config.mos->tcp_timeout =
208 			SEC_TO_USEC(g_config.mos->tcp_timeout) / TIME_TICK;
209 	else if (TRY_ASSIGN_NUM(no_ring_buffers, conf, item, value));
210 	else if (TRY_ASSIGN_STR(mos_log,         conf, item, value));
211 	else if (TRY_ASSIGN_STR(stat_print,      conf, item, value));
212 	else if (TRY_ASSIGN_STR(port,            conf, item, value));
213 	else if (strcmp(item, "multiprocess") == 0) {
214 		conf->multiprocess = 1;
215 		SetMultiProcessSupport(value);
216 	}
217 }
218 /*----------------------------------------------------------------------------*/
219 static void
220 FeedNetdevConfLine(struct conf_block *blk, char *line, int len)
221 {
222 	struct netdev_conf * const conf = (struct netdev_conf *)blk->conf;
223 
224 #ifndef DARWIN
225 	int i;
226 #endif
227 	uint64_t cpu_mask;
228 	char *word = NULL;
229 	int wlen;
230 
231 	if (DetectWord(line, len, &word, &wlen) < 0 || wlen > WORD_LEN || wlen <= 0)
232 		return;
233 
234 	line = word + wlen;
235 
236 	if (sscanf(line, "%li", &cpu_mask) <= 0)
237 		return;
238 
239 	struct netdev_entry *ent = calloc(1, sizeof(struct netdev_entry));
240 	if (!ent) {
241 		TRACE_ERROR("Could not allocate memory for netdev_entry!\n");
242 		exit(EXIT_FAILURE);
243 	}
244 
245 	strncpy(ent->dev_name, word, wlen);
246 	ent->cpu_mask = cpu_mask;
247 	g_config.mos->cpu_mask |= cpu_mask;
248 
249 	strncpy(ent->ifr.ifr_name, ent->dev_name, IFNAMSIZ);
250 	ent->ifr.ifr_name[IFNAMSIZ] = '\0';
251 
252 #ifdef ENABLE_DPDKR
253 #define DPDKR_PORT_DIR "/usr/local/var/run/openvswitch/port/"
254 	char dpdkr_ip_path[MAX_PROCLINE_LEN];
255 	char dpdkr_mac_path[MAX_PROCLINE_LEN];
256 	char dpdkr_netmask_path[MAX_PROCLINE_LEN];
257 	char dpdkr_gateway_path[MAX_PROCLINE_LEN];
258 	char dpdkr_line[MAX_PROCLINE_LEN];
259 	FILE* fp;
260 	struct in_addr addr;
261 
262 	sprintf(dpdkr_ip_path, "%s%s/ip", DPDKR_PORT_DIR, ent->ifr.ifr_name);
263 	sprintf(dpdkr_mac_path, "%s%s/mac", DPDKR_PORT_DIR, ent->ifr.ifr_name);
264 	sprintf(dpdkr_netmask_path, "%s%s/netmask", DPDKR_PORT_DIR, ent->ifr.ifr_name);
265 	sprintf(dpdkr_gateway_path, "%s%s/gateway", DPDKR_PORT_DIR, ent->ifr.ifr_name);
266 
267 	/* For DPDKR ports, we need to get port info from a file */
268 	/* (1) ip address */
269 	if ((fp = fopen(dpdkr_ip_path, "r")) == NULL ||
270 		fgets(dpdkr_line, sizeof(dpdkr_line), fp) == (char *) NULL) {
271 		perror(dpdkr_ip_path);
272 		exit(EXIT_FAILURE);
273 	}
274 	if (inet_aton(dpdkr_line, &addr) == 0) {
275 		TRACE_ERROR("Invalid address for port %s: %s (please check %s).\n",
276 					ent->ifr.ifr_name, dpdkr_line, dpdkr_ip_path);
277 		exit(EXIT_FAILURE);
278 	}
279 	ent->ip_addr = *(uint32_t *)&addr;
280 	fclose(fp);
281 
282 	/* (2) mac address */
283 	memset(dpdkr_line, 0, MAX_PROCLINE_LEN);
284 	if ((fp = fopen(dpdkr_mac_path, "r")) == NULL ||
285 		fgets(dpdkr_line, sizeof(dpdkr_line), fp) == (char *) NULL) {
286 		perror(dpdkr_mac_path);
287 		exit(EXIT_FAILURE);
288 	}
289 	if (sscanf(dpdkr_line, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
290 			   &ent->haddr[0], &ent->haddr[1], &ent->haddr[2],
291 			   &ent->haddr[3], &ent->haddr[4], &ent->haddr[5]) != 6) {
292 		TRACE_ERROR("Invalid address for port %s: %s (please check %s).\n",
293 					ent->ifr.ifr_name, dpdkr_line, dpdkr_mac_path);
294 		exit(EXIT_FAILURE);
295 	}
296 	fclose(fp);
297 
298 	/* (3) netmask */
299 	memset(dpdkr_line, 0, MAX_PROCLINE_LEN);
300 	if ((fp = fopen(dpdkr_netmask_path, "r")) == NULL ||
301 		fgets(dpdkr_line, sizeof(dpdkr_line), fp) == (char *) NULL) {
302 		perror(dpdkr_netmask_path);
303 		exit(EXIT_FAILURE);
304 	}
305 	if (inet_aton(dpdkr_line, &addr) == 0) {
306 		TRACE_ERROR("Invalid address for port %s: %s (please check %s).\n",
307 					ent->ifr.ifr_name, dpdkr_line, dpdkr_netmask_path);
308 		exit(EXIT_FAILURE);
309 	}
310 	ent->netmask = *(uint32_t *)&addr;
311 	fclose(fp);
312 
313 	/* (4) default gateway */
314 	memset(dpdkr_line, 0, MAX_PROCLINE_LEN);
315 	if ((fp = fopen(dpdkr_gateway_path, "r")) == NULL ||
316 		fgets(dpdkr_line, sizeof(dpdkr_line), fp) == (char *) NULL) {
317 		perror(dpdkr_gateway_path);
318 		exit(EXIT_FAILURE);
319 	}
320 	if (inet_aton(dpdkr_line, &addr) == 0) {
321 		TRACE_ERROR("Invalid address for port %s: %s (please check %s).\n",
322 					ent->ifr.ifr_name, dpdkr_line, dpdkr_gateway_path);
323 		exit(EXIT_FAILURE);
324 	}
325 	ent->gateway = *(uint32_t *)&addr;
326 	fclose(fp);
327 
328 	ent->ifindex = -1;
329 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
330 	conf->ent[conf->num] = ent;
331 	conf->num++;
332 	return;
333 #endif
334 
335 	/* Create socket */
336 	int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
337 	if (sock == -1) {
338 		perror("socket");
339 	}
340 
341 	/* getting address */
342 	if (ioctl(sock, SIOCGIFADDR, &ent->ifr) == 0 ) {
343 		struct in_addr sin = ((struct sockaddr_in *)&ent->ifr.ifr_addr)->sin_addr;
344 		ent->ip_addr = *(uint32_t *)&sin;
345 	}
346 
347 	/* Net MASK */
348 	if (ioctl(sock, SIOCGIFNETMASK, &ent->ifr) == 0) {
349 		struct in_addr sin = ((struct sockaddr_in *)&ent->ifr.ifr_addr)->sin_addr;
350 		ent->netmask = *(uint32_t *)&sin;
351 	}
352 
353 #ifdef DARWIN
354 	/* FIXME: How can I retrieve a mac address in MAC OS? */
355 #else
356 	if (ioctl(sock, SIOCGIFHWADDR, &ent->ifr) == 0 ) {
357 		for (i = 0; i < 6; i ++) {
358 			ent->haddr[i] = ent->ifr.ifr_addr.sa_data[i];
359 		}
360 	}
361 #endif
362 
363 	close(sock);
364 
365 	ent->ifindex = -1;
366 
367 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
368 	conf->ent[conf->num] = ent;
369 	conf->num++;
370 }
371 /*----------------------------------------------------------------------------*/
372 static void
373 FeedArpConfLine(struct conf_block *blk, char *line, int len)
374 {
375 	struct arp_conf * const conf = (struct arp_conf *)blk->conf;
376 
377 	char address[WORD_LEN];
378 	int prefix;
379 	uint8_t haddr[ETH_ALEN] = {0};
380 
381 	/* skip first space */
382 	while (isspace(*line))
383 		line++, len--;
384 
385 	if (sscanf(line, "%[0-9.]/%d %hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
386 				address, &prefix, &haddr[0], &haddr[1], &haddr[2],
387 				&haddr[3], &haddr[4], &haddr[5]) != 8)
388 		return;
389 
390 	struct _arp_entry *ent = calloc(1, sizeof(struct _arp_entry));
391 	if (!ent) {
392 		TRACE_ERROR("Could not allocate memory for arp_entry!\n");
393 		exit(EXIT_FAILURE);
394 	}
395 
396 	ent->ip = inet_addr(address);
397 	ent->prefix = prefix;
398 	ent->mask = htonl((prefix == 0) ? 0 : ((-1) << (32 - prefix)));
399 	ent->masked_ip = ent->mask & ent->ip;
400 	memcpy(ent->haddr, haddr, ETH_ALEN);
401 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
402 	conf->ent[conf->num] = ent;
403 	conf->num++;
404 }
405 /*----------------------------------------------------------------------------*/
406 static void
407 FeedRouteConfLine(struct conf_block *blk, char *line, int len)
408 {
409 	struct route_conf * const conf = (struct route_conf *)blk->conf;
410 
411 	char address[WORD_LEN], dev_name[WORD_LEN];
412 	int prefix;
413 
414 	/* skip first space */
415 	while (isspace(*line))
416 		line++, len--;
417 
418 	if (sscanf(line, "%[0-9.]/%d %[^ ^\n^\t]", address, &prefix, dev_name) != 3)
419 		return;
420 
421 	struct route_entry *ent = calloc(1, sizeof(struct route_entry));
422 	if (!ent) {
423 		TRACE_ERROR("Could not allocate memory for route_entry!\n");
424 		exit(EXIT_FAILURE);
425 	}
426 
427 	ent->ip = inet_addr(address);
428 	ent->mask = htonl((prefix == 0) ? 0 : ((-1) << (32 - prefix)));
429 	ent->masked_ip = ent->mask & ent->ip;
430 	ent->prefix = prefix;
431 	ent->nif = -1;
432 	strcpy(ent->dev_name, dev_name);
433 
434 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
435 	conf->ent[conf->num] = ent;
436 	conf->num++;
437 }
438 /*----------------------------------------------------------------------------*/
439 static void
440 FeedNICFwdConfLine(struct conf_block *blk, char *line, int len)
441 {
442 	struct nic_forward_conf * const conf = (struct nic_forward_conf *)blk->conf;
443 	char dev_name_in[WORD_LEN];
444 	char dev_name_out[WORD_LEN];
445 
446 	/* skip first space */
447 	while (isspace(*line))
448 		line++, len--;
449 
450 	if (sscanf(line, "%[^ ^\n^\t] %[^ ^\n^\t]", dev_name_in, dev_name_out) != 2)
451 		return;
452 
453 	struct nic_forward_entry *ent = calloc(1, sizeof(struct nic_forward_entry));
454 	if (!ent) {
455 		TRACE_ERROR("Could not allocate memory for nic forward entry!\n");
456 		exit(EXIT_FAILURE);
457 	}
458 
459 	strcpy(ent->nif_in, dev_name_in);
460 	strcpy(ent->nif_out, dev_name_out);
461 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
462 	conf->ent[conf->num] = ent;
463 	conf->num++;
464 }
465 /*----------------------------------------------------------------------------*/
466 static void
467 MosConfAddChild(struct conf_block *blk, struct conf_block *child)
468 {
469 	struct mos_conf * const conf = (struct mos_conf *)blk->conf;
470 
471 	if (strcmp(child->name, NETDEV_BLOCK_NAME) == 0) {
472 		conf->netdev = child;
473 		conf->netdev_table = (struct netdev_conf *)child->conf;
474 	} else if (strcmp(child->name, ARP_BLOCK_NAME) == 0) {
475 		conf->arp = child;
476 		conf->arp_table = (struct arp_conf *)child->conf;
477 	} else if (strcmp(child->name, ROUTE_BLOCK_NAME) == 0) {
478 		conf->route = child;
479 		conf->route_table = (struct route_conf *)child->conf;
480 	} else if (strcmp(child->name, FORWARD_BLOCK_NAME) == 0) {
481 		conf->nic_forward = child;
482 		conf->nic_forward_table = (struct nic_forward_conf *)child->conf;
483 	} else
484 		return;
485 }
486 /*----------------------------------------------------------------------------*/
487 static int
488 AppConfIsValid(struct conf_block *blk)
489 {
490 	struct app_conf * const conf = (struct app_conf *)blk->conf;
491 
492 	if (conf->app_argc <= 0)
493 		return 0;
494 
495 	return 1;
496 }
497 /*----------------------------------------------------------------------------*/
498 static int
499 MosConfIsValid(struct conf_block *blk)
500 {
501 	return 1;
502 }
503 /*----------------------------------------------------------------------------*/
504 static int
505 NetdevConfIsValid(struct conf_block *blk)
506 {
507 	return 1;
508 }
509 /*----------------------------------------------------------------------------*/
510 static int
511 ArpConfIsValid(struct conf_block *blk)
512 {
513 	return 1;
514 }
515 /*----------------------------------------------------------------------------*/
516 static int
517 RouteConfIsValid(struct conf_block *blk)
518 {
519 	return 1;
520 }
521 /*----------------------------------------------------------------------------*/
522 static int
523 NICFwdConfIsValid(struct conf_block *blk)
524 {
525 	return 1;
526 }
527 /*----------------------------------------------------------------------------*/
528 static void
529 NetdevConfPrint(struct conf_block *blk)
530 {
531 	struct netdev_conf * const conf = (struct netdev_conf *)blk->conf;
532 
533 	printf(" +===== Netdev configuration (%d entries) =====\n",
534 			conf->num);
535 
536 	struct netdev_entry *walk;
537 	TAILQ_FOREACH(walk, &conf->list, link) {
538 		printf(" | %s(idx: %d, HADDR: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX) maps to CPU 0x%016lX\n",
539 				walk->dev_name, walk->ifindex,
540 				walk->haddr[0], walk->haddr[1], walk->haddr[2],
541 				walk->haddr[3], walk->haddr[4], walk->haddr[5],
542 				walk->cpu_mask);
543 	}
544 	printf(" |\n");
545 }
546 /*----------------------------------------------------------------------------*/
547 static void
548 ArpConfPrint(struct conf_block *blk)
549 {
550 	struct arp_conf * const conf = (struct arp_conf *)blk->conf;
551 
552 	printf(" +===== Static ARP table configuration (%d entries) =====\n",
553 			conf->num);
554 
555 	struct _arp_entry *walk;
556 	TAILQ_FOREACH(walk, &conf->list, link) {
557 		printf(" | IP: 0x%08X, NETMASK: 0x%08X, "
558 			   "HADDR: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX\n",
559 			   ntohl(walk->ip), ntohl(walk->mask),
560 			   walk->haddr[0], walk->haddr[1], walk->haddr[2],
561 			   walk->haddr[3], walk->haddr[4], walk->haddr[5]);
562 	}
563 	printf(" |\n");
564 }
565 /*----------------------------------------------------------------------------*/
566 static void
567 RouteConfPrint(struct conf_block *blk)
568 {
569 	struct route_conf * const conf = (struct route_conf *)blk->conf;
570 
571 	printf(" +===== Routing table configuration (%d entries) =====\n",
572 			conf->num);
573 
574 	struct route_entry *walk;
575 	TAILQ_FOREACH(walk, &conf->list, link) {
576 		printf(" | IP: 0x%08X, NETMASK: 0x%08X, INTERFACE: %s(idx: %d)\n",
577 			   ntohl(walk->ip), ntohl(walk->mask), walk->dev_name, walk->nif);
578 	}
579 	printf(" |\n");
580 }
581 /*----------------------------------------------------------------------------*/
582 static void
583 NICFwdConfPrint(struct conf_block *blk)
584 {
585 	int i;
586 	struct nic_forward_conf * const conf = (struct nic_forward_conf *)blk->conf;
587 
588 	printf(" +===== NIC Forwarding table configuration (%d entries) =====\n",
589 			conf->num);
590 
591 	struct nic_forward_entry *walk;
592 	TAILQ_FOREACH(walk, &conf->list, link) {
593 		printf(" | NIC Forwarding Entry: %s <---> %s",
594 		       walk->nif_in, walk->nif_out);
595 	}
596 	printf(" |\n");
597 
598 	printf(" | NIC Forwarding Index Table: |\n");
599 
600 	for (i = 0; i < MAX_FORWARD_ENTRY; i++)
601 		printf( " | %d --> %d | \n", i, conf->nic_fwd_table[i]);
602 }
603 /*----------------------------------------------------------------------------*/
604 static void
605 AppConfPrint(struct conf_block *blk)
606 {
607 	struct app_conf * const conf = (struct app_conf *)blk->conf;
608 
609 	printf("===== Application configuration =====\n");
610 	printf("| type:       %s\n", conf->type);
611 	printf("| run:        %s\n", conf->run);
612 	printf("| cpu_mask:   0x%016lX\n", conf->cpu_mask);
613 	printf("| ip_forward: %s\n", conf->ip_forward ? "forward" : "drop");
614 	printf("\n");
615 }
616 /*----------------------------------------------------------------------------*/
617 static void
618 MosConfPrint(struct conf_block *blk)
619 {
620 	struct mos_conf * const conf = (struct mos_conf *)blk->conf;
621 
622 	printf("===== MOS configuration =====\n");
623 	printf("| num_cores:       %d\n", conf->num_cores);
624 	printf("| nb_mem_channels: %d\n", conf->nb_mem_channels);
625 	printf("| max_concurrency: %d\n", conf->max_concurrency);
626 	printf("| rmem_size:       %d\n", conf->rmem_size);
627 	printf("| wmem_size:       %d\n", conf->wmem_size);
628 	printf("| tcp_tw_interval: %d\n", conf->tcp_tw_interval);
629 	printf("| tcp_timeout:     %d\n", conf->tcp_timeout);
630 	printf("| multiprocess:    %s\n", conf->multiprocess ? "true" : "false");
631 	printf("| mos_log:         %s\n", conf->mos_log);
632 	printf("| stat_print:      %s\n", conf->stat_print);
633 	printf("| forward:         %s\n", conf->forward ? "forward" : "drop");
634 	printf("|\n");
635 	if (conf->netdev)
636 		conf->netdev->print(conf->netdev);
637 	if (conf->arp)
638 		conf->arp->print(conf->arp);
639 	if (conf->route)
640 		conf->route->print(conf->route);
641 	if (conf->nic_forward)
642 		conf->nic_forward->print(conf->nic_forward);
643 	printf("\n");
644 }
645 /*----------------------------------------------------------------------------*/
646 static void
647 InitAppBlock(struct config *config, struct conf_block *blk)
648 {
649 	assert(blk);
650 
651 	blk->name = APP_BLOCK_NAME;
652 
653 	blk->feed = FeedAppConfLine;
654 	blk->addchild = NULL;
655 	blk->isvalid = AppConfIsValid;
656 	blk->print = AppConfPrint;
657 
658 	struct app_conf *conf = calloc(1, sizeof(struct app_conf));
659 	if (conf == NULL) {
660 		TRACE_ERROR("Could not allocate memory for app_conf!\n");
661 		exit(EXIT_FAILURE);
662 	}
663 	/* set default values */
664 	conf->cpu_mask = -1;
665 	conf->ip_forward = 1;
666 	conf->app_argc = 0;
667 	blk->conf = conf;
668 
669 	blk->list = (typeof(blk->list))&config->app_blkh;
670 }
671 /*----------------------------------------------------------------------------*/
672 static void
673 InitMosBlock(struct config *config, struct conf_block *blk)
674 {
675 	assert(blk);
676 
677 	blk->name = MOS_BLOCK_NAME;
678 
679 	blk->feed = FeedMosConfLine;
680 	blk->addchild = MosConfAddChild;
681 	blk->isvalid = MosConfIsValid;
682 	blk->print = MosConfPrint;
683 
684 	struct mos_conf *conf = calloc(1, sizeof(struct mos_conf));
685 	if (conf == NULL) {
686 		TRACE_ERROR("Could not allocate memory for mos_conf!\n");
687 		exit(EXIT_FAILURE);
688 	}
689 	/* set default values */
690 	conf->forward = 1;
691 	conf->nb_mem_channels = 0;
692 	conf->max_concurrency = 100000;
693 	conf->no_ring_buffers = 0;
694 	conf->rmem_size = 8192;
695 	conf->wmem_size = 8192;
696 	conf->tcp_tw_interval = SEC_TO_USEC(TCP_TIMEWAIT) / TIME_TICK;
697 	conf->tcp_timeout = SEC_TO_USEC(TCP_TIMEOUT) / TIME_TICK;
698 	conf->cpu_mask = 0;
699 	blk->conf = conf;
700 
701 	blk->list = (typeof(blk->list))&config->mos_blkh;
702 	config->mos = conf;
703 }
704 /*----------------------------------------------------------------------------*/
705 static void
706 InitNetdevBlock(struct config *config, struct conf_block *blk)
707 {
708 	assert(blk);
709 
710 	blk->name = NETDEV_BLOCK_NAME;
711 
712 	blk->feed = FeedNetdevConfLine;
713 	blk->addchild = NULL;
714 	blk->isvalid = NetdevConfIsValid;
715 	blk->print = NetdevConfPrint;
716 
717 	struct netdev_conf *conf = calloc(1, sizeof(struct netdev_conf));
718 	if (conf == NULL) {
719 		TRACE_ERROR("Could not allocate memory for netdev_conf!\n");
720 		exit(EXIT_FAILURE);
721 	}
722 	TAILQ_INIT(&conf->list);
723 	blk->conf = conf;
724 
725 	blk->list = NULL;
726 }
727 /*----------------------------------------------------------------------------*/
728 static void
729 FetchARPKernelEntries(struct arp_conf * const config)
730 {
731 #define	_PATH_PROCNET_ARP		"/proc/net/arp"
732 #define	DPDK_PREFIX			"dpdk"
733 #define DPDK_PREFIX_LEN			4
734 #define LINE_LEN			200
735 #define ENTRY_LEN			25
736 
737 	FILE *fp;
738 	char ip[ENTRY_LEN];
739 	char hwa[ENTRY_LEN];
740 	char mask[ENTRY_LEN];
741 	char dev[WORD_LEN];
742 	char line[LINE_LEN];
743 	int type, flags, num;
744 
745 	if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
746 		perror(_PATH_PROCNET_ARP);
747 		exit(EXIT_FAILURE);
748 	}
749 
750 	/* Bypass header -- read until newline */
751 	if (fgets(line, sizeof(line), fp) != (char *) NULL) {
752 		strcpy(mask, "-");
753 		strcpy(dev, "-");
754 		/* Read the ARP cache entries. */
755 		for (; fgets(line, sizeof(line), fp);) {
756 
757 			num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
758 				     ip, &type, &flags, hwa, mask, dev);
759 			if (num < 6)
760 				break;
761 
762 			/* if the user specified device differs, skip it */
763 			if (strncmp(dev, DPDK_PREFIX, DPDK_PREFIX_LEN))
764 				continue;
765 
766 			/* if the entry has not expired/tagged for removal then... */
767 			if (flags != 0x00) {
768 				/* add the new arp entry in MOS database */
769 				struct _arp_entry *ent = calloc(1, sizeof(struct _arp_entry));
770 				if (!ent) {
771 					TRACE_ERROR("Can't allocate memory for arp_entry\n");
772 					exit(EXIT_FAILURE);
773 				}
774 				uint8_t haddr[ETH_ALEN] = {0};
775 				if (sscanf(hwa, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
776 					   &haddr[0], &haddr[1], &haddr[2],
777 					   &haddr[3], &haddr[4], &haddr[5]) != 6) {
778 					TRACE_ERROR("Error reading the ARP entry\n");
779 					exit(EXIT_FAILURE);
780 				}
781 				ent->ip = inet_addr(ip);
782 				ent->prefix = 32;
783 				ent->mask = htonl((ent->prefix == 0) ? 0 : ((-1) << (32 - ent->prefix)));
784 				ent->masked_ip = ent->mask & ent->ip;
785 				memcpy(ent->haddr, haddr, ETH_ALEN);
786 				TAILQ_INSERT_TAIL(&config->list, ent, link);
787 				config->ent[config->num] = ent;
788 				config->num++;
789 			}
790 		}
791 	}
792 
793 	fclose(fp);
794 }
795 /*----------------------------------------------------------------------------*/
796 static void
797 FetchRouteKernelEntries(struct route_conf * const config)
798 {
799 #define	_PATH_PROCNET_ROUTE		"/proc/net/route"
800 #define	DPDK_PREFIX			"dpdk"
801 #define DPDK_PREFIX_LEN			4
802 
803 	FILE *fp;
804 	uint32_t gate;
805 	uint32_t dest;
806 	uint32_t mask;
807 	char dev[WORD_LEN];
808 	char line[LINE_LEN];
809 	char mtu[ENTRY_LEN];
810 	char win[ENTRY_LEN];
811 	char irtt[ENTRY_LEN];
812 	int flags, num, cnt, use, metric;
813 
814 	if ((fp = fopen(_PATH_PROCNET_ROUTE, "r")) == NULL) {
815 		perror(_PATH_PROCNET_ARP);
816 		exit(EXIT_FAILURE);
817 	}
818 
819 	/* Bypass header -- read until newline */
820 	if (fgets(line, sizeof(line), fp) != (char *) NULL) {
821 		/* Read the route table entries. */
822 		for (; fgets(line, sizeof(line), fp);) {
823 
824 			num = sscanf(line, "%s %08X %08X %d %d %d %d %08X %s %s %s\n",
825 				     dev,
826 				     &dest,
827 				     &gate,
828 				     &flags, &cnt, &use, &metric,
829 				     &mask,
830 				     mtu, win, irtt);
831 
832 			if (num < 11)
833 				break;
834 #if 0
835 			/* if the user specified device differs, skip it */
836 			if (strncmp(dev, DPDK_PREFIX, DPDK_PREFIX_LEN))
837 				continue;
838 #endif
839 			struct route_entry *ent = calloc(1, sizeof(struct route_entry));
840 			if (!ent) {
841 				TRACE_ERROR("Could not allocate memory for route_entry!\n");
842 				exit(EXIT_FAILURE);
843 			}
844 
845 			ent->ip = dest;
846 			ent->prefix = 32 - __builtin_clz(mask);
847 			ent->mask = mask;
848 			ent->masked_ip = ent->mask & ent->ip;
849 			strcpy(ent->dev_name, dev);
850 			TAILQ_INSERT_TAIL(&config->list, ent, link);
851 			config->ent[config->num] = ent;
852 			config->num++;
853 		}
854 	}
855 
856 	fclose(fp);
857 }
858 /*----------------------------------------------------------------------------*/
859 static void
860 InitArpBlock(struct config *config, struct conf_block *blk)
861 {
862 	assert(blk);
863 
864 	blk->name = ARP_BLOCK_NAME;
865 
866 	blk->feed = FeedArpConfLine;
867 	blk->addchild = NULL;
868 	blk->isvalid = ArpConfIsValid;
869 	blk->print = ArpConfPrint;
870 
871 	struct arp_conf *conf = calloc(1, sizeof(struct arp_conf));
872 	if (conf == NULL) {
873 		TRACE_ERROR("Could not allocate memory for arp_conf!\n");
874 		exit(EXIT_FAILURE);
875 	}
876 	TAILQ_INIT(&conf->list);
877 	blk->conf = conf;
878 
879 	blk->list = NULL;
880 	config->mos->arp = blk;
881 
882 	/* fetch relevant ARP entries for dpdk? from kernel tables */
883 	FetchARPKernelEntries(conf);
884 }
885 /*----------------------------------------------------------------------------*/
886 static void
887 InitRouteBlock(struct config *config, struct conf_block *blk)
888 {
889 	assert(blk);
890 
891 	blk->name = ROUTE_BLOCK_NAME;
892 
893 	blk->feed = FeedRouteConfLine;
894 	blk->addchild = NULL;
895 	blk->isvalid = RouteConfIsValid;
896 	blk->print = RouteConfPrint;
897 
898 	struct route_conf *conf = calloc(1, sizeof(struct route_conf));
899 	if (conf == NULL) {
900 		TRACE_ERROR("Could not allocate memory for route_conf!\n");
901 		exit(EXIT_FAILURE);
902 	}
903 	TAILQ_INIT(&conf->list);
904 	blk->conf = conf;
905 
906 	blk->list = NULL;
907 	config->mos->route = blk;
908 
909 	/* fetch relevant route entries for dpdk? from kernel tables */
910 	FetchRouteKernelEntries(conf);
911 }
912 /*----------------------------------------------------------------------------*/
913 static void
914 InitNICForwardBlock(struct config *config, struct conf_block *blk)
915 {
916 	int i;
917 	assert(blk);
918 	blk->name = FORWARD_BLOCK_NAME;
919 
920 	blk->feed = FeedNICFwdConfLine;
921 	blk->addchild = NULL;
922 	blk->isvalid = NICFwdConfIsValid;
923 	blk->print = NICFwdConfPrint;
924 
925 	struct nic_forward_conf *conf = calloc(1, sizeof(struct nic_forward_conf));
926 	if (conf == NULL) {
927 		TRACE_ERROR("Could not allocate memory for nic_forward_conf!\n");
928 		exit(EXIT_FAILURE);
929 	}
930 	for (i = 0; i < MAX_FORWARD_ENTRY; i++)
931 		conf->nic_fwd_table[i] = -1;
932 
933 	TAILQ_INIT(&conf->list);
934 	blk->conf = conf;
935 
936 	blk->list = NULL;
937 	config->mos->nic_forward = blk;
938 }
939 /*----------------------------------------------------------------------------*/
940 void
941 PrintConf(struct config *conf)
942 {
943 	struct conf_block *walk;
944 	TAILQ_FOREACH(walk, &conf->app_blkh, link) {
945 		if (walk->print)
946 			walk->print(walk);
947 	}
948 
949 	TAILQ_FOREACH(walk, &conf->mos_blkh, link) {
950 		if (walk->print)
951 			walk->print(walk);
952 	}
953 }
954 /*----------------------------------------------------------------------------*/
955 static void
956 CheckConfValidity(struct config *conf)
957 {
958 	struct conf_block *walk;
959 	TAILQ_FOREACH(walk, &conf->app_blkh, link) {
960 		if (!walk->isvalid || !walk->isvalid(walk))
961 			goto __error;
962 	}
963 
964 	TAILQ_FOREACH(walk, &conf->mos_blkh, link) {
965 		struct conf_block *child;
966 
967 		if (!walk->isvalid || !walk->isvalid(walk))
968 			goto __error;
969 
970 		child = ((struct mos_conf *)walk->conf)->netdev;
971 		if (!child->isvalid || !child->isvalid(child))
972 			goto __error;
973 
974 		child = ((struct mos_conf *)walk->conf)->arp;
975 		if (!child->isvalid || !child->isvalid(child))
976 			goto __error;
977 
978 		child = ((struct mos_conf *)walk->conf)->route;
979 		if (!child->isvalid || !child->isvalid(child))
980 			goto __error;
981 	}
982 
983 	return;
984 
985 __error:
986 	printf("!!!!! Configuration validity check failure !!!!!\n");
987 	if (walk && walk->print)
988 		walk->print(walk);
989 	exit(0);
990 }
991 /*----------------------------------------------------------------------------*/
992 static char *
993 ReadConf(const char *fname)
994 {
995 	size_t hav_read = 0;
996 	FILE *fp = fopen(fname, "r");
997 	if (fp == NULL) {
998 		TRACE_ERROR("Cannot open the config file %s\n", fname);
999 		exit(-1);
1000 	}
1001 
1002 	/* find out the size of file */
1003 	fseek(fp, 0L, SEEK_END);
1004 	int size = ftell(fp);
1005 	fseek(fp, 0L, SEEK_SET);
1006 
1007 	file = calloc(1, size + 1);
1008 	if (file == NULL) {
1009 		TRACE_ERROR("Can't allocate memory for file!\n");
1010 		exit(EXIT_FAILURE);
1011 	}
1012 
1013 	file[size] = '\0';
1014 
1015 	while ((hav_read += fread(file, 1, size, fp)) < size);
1016 
1017 	fclose(fp);
1018 
1019 	return file;
1020 }
1021 /*----------------------------------------------------------------------------*/
1022 static char *
1023 PreprocessConf(char *raw)
1024 {
1025 	char *line;
1026 	int llen;
1027 
1028 	int len = strlen(raw);
1029 
1030 	LINE_FOREACH(line, llen, raw, len) {
1031 		int i, iscomment = 0;
1032 		for (i = 0; i < llen; i++) {
1033 			if (!iscomment && line[i] == '#')
1034 				iscomment = 1;
1035 			if (iscomment)
1036 				line[i] = ' ';
1037 		}
1038 	}
1039 	return raw;
1040 }
1041 /*----------------------------------------------------------------------------*/
1042 static void
1043 InitConfig(struct config *config)
1044 {
1045 	int i;
1046 	struct conf_block *blk;
1047 
1048 	TAILQ_INIT(&g_free_blkh);
1049 	TAILQ_INIT(&config->app_blkh);
1050 	TAILQ_INIT(&config->mos_blkh);
1051 
1052 	for (i = 0; i < MAX_APP_BLOCK; i++) {
1053 		/* Allocate app conf_block */
1054 		blk = calloc(1, sizeof(struct conf_block));
1055 		if (blk == NULL) goto init_config_err;
1056 		InitAppBlock(config, blk);
1057 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1058 
1059 		/* Allocate netdev conf_block */
1060 		blk = calloc(1, sizeof(struct conf_block));
1061 		if (blk == NULL) goto init_config_err;
1062 		InitNetdevBlock(config, blk);
1063 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1064 	}
1065 
1066 	for (i = 0; i < MAX_MOS_BLOCK; i++) {
1067 		/* Allocate mos conf_block */
1068 		blk = calloc(1, sizeof(struct conf_block));
1069 		if (blk == NULL) goto init_config_err;
1070 		InitMosBlock(config, blk);
1071 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1072 
1073 		/* Allocate arp conf_block */
1074 		blk = calloc(1, sizeof(struct conf_block));
1075 		if (blk == NULL) goto init_config_err;
1076 		InitArpBlock(config, blk);
1077 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1078 
1079 		/* Allocate route conf_block */
1080 		blk = calloc(1, sizeof(struct conf_block));
1081 		if (blk == NULL) goto init_config_err;
1082 		InitRouteBlock(config, blk);
1083 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1084 
1085 		/* Allocate nic_forward conf_block */
1086 		blk = calloc (1, sizeof(struct conf_block));
1087 		if (blk == NULL) goto init_config_err;
1088 		InitNICForwardBlock(config, blk);
1089 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1090 	}
1091 	return;
1092  init_config_err:
1093 	TRACE_ERROR("Can't allocate memory for blk_entry!\n");
1094 	exit(EXIT_FAILURE);
1095 }
1096 /*----------------------------------------------------------------------------*/
1097 static struct conf_block *
1098 AllocateBlock(char *name, int len)
1099 {
1100 	struct conf_block *walk, *tmp;
1101 
1102 	for (walk = TAILQ_FIRST(&g_free_blkh); walk != NULL; walk = tmp) {
1103 		tmp = TAILQ_NEXT(walk, link);
1104 		if (len == strlen(walk->name) && strncmp(walk->name, name, len) == 0) {
1105 			TAILQ_REMOVE(&g_free_blkh, walk, link);
1106 			if (walk->list)
1107 				TAILQ_INSERT_TAIL(walk->list, walk, link);
1108 			return walk;
1109 		}
1110 	}
1111 
1112 	return NULL;
1113 }
1114 /*----------------------------------------------------------------------------*/
1115 struct conf_block *
1116 DetectBlock(struct conf_block *blk, char *buf, int len)
1117 {
1118 	int depth = 0;
1119 	char *blkname = NULL, *end = &buf[len];
1120 	int blknamelen;
1121 	struct conf_block *nblk;
1122 
1123 	/* skip first space */
1124 	while (buf < end && isspace(*buf))
1125 		buf++;
1126 
1127 	if (DetectWord(buf, len, &blkname, &blknamelen) < 0
1128 			|| blkname != buf)
1129 		/* Failed to detect conf_block name */
1130 		return NULL;
1131 
1132 	/* fast forward buffer */
1133 	buf += blknamelen;
1134 
1135 	/* skip space */
1136 	while (buf < end && isspace(*buf))
1137 		buf++;
1138 
1139 	/* buf must be '{' */
1140 	if (buf >= end || *buf != '{')
1141 		return NULL;
1142 
1143 	buf++;   /* skip '{' */
1144 	while (buf < end && isspace(*buf))
1145 		buf++; /* skip space */
1146 	depth++; /* Now in first parenthesis */
1147 
1148 	/* Now, the `buf` points the first byte inside conf_block */
1149 
1150 	for (len = 0; &buf[len] < end; len++) {
1151 		if (buf[len] == '{')
1152 			depth++;
1153 		else if (buf[len] == '}' && --depth == 0)
1154 				break;
1155 	}
1156 
1157 	if (depth != 0)
1158 		/* Failed to find the end of parenthesis */
1159 		return NULL;
1160 
1161 	if (!(nblk = AllocateBlock(blkname, blknamelen)))
1162 		return NULL;
1163 
1164 	if (blk) {
1165 		assert(blk->addchild);
1166 		blk->addchild(blk, nblk);
1167 	}
1168 
1169 	nblk->buf = buf;
1170 	nblk->len = len;
1171 
1172 	return nblk;
1173 }
1174 /*----------------------------------------------------------------------------*/
1175 static void
1176 ParseBlock(struct conf_block *blk)
1177 {
1178 	char *line;
1179 	int llen;
1180 
1181 	LINE_FOREACH(line, llen, blk->buf, blk->len) {
1182 		struct conf_block *nblk;
1183 
1184 		if ((nblk = DetectBlock(blk, line, blk->len - (line - blk->buf)))) {
1185 			ParseBlock(nblk);
1186 			/* skip nested conf_block by fast forwarding line */
1187 			line = &nblk->buf[nblk->len] + 1;
1188 			llen = 0;
1189 		} else
1190 			blk->feed(blk, line, llen);
1191 	}
1192 }
1193 /*----------------------------------------------------------------------------*/
1194 void
1195 PatchCONFIG(struct config *config)
1196 {
1197 	int i;
1198 	char *word, *str, *end;
1199 	int wlen;
1200 
1201 	g_config.mos->num_cores = num_cpus;
1202 	word = NULL;
1203 
1204 	i = 0;
1205 	struct conf_block *bwalk;
1206 	TAILQ_FOREACH(bwalk, &g_config.app_blkh, link) {
1207 		struct app_conf *app_conf = (struct app_conf *)bwalk->conf;
1208 		g_config.mos->forward = g_config.mos->forward && app_conf->ip_forward;
1209 		if (end_app_exists == 0 && !strcmp(app_conf->type, "end"))
1210 			end_app_exists = 1;
1211 		if (mon_app_exists == 0 && !strcmp(app_conf->type, "monitor"))
1212 			mon_app_exists = 1;
1213 		i++;
1214 	}
1215 	/* turn on monitor mode if end app is not set */
1216 	if (!end_app_exists && !mon_app_exists) mon_app_exists = 1;
1217 
1218 	/* stat print */
1219 	str = g_config.mos->stat_print;
1220 	end = str + strlen(str);
1221 	while (DetectWord(str, end - str, &word, &wlen) == 0) {
1222 		for (i = 0; i < g_config.mos->netdev_table->num; i++) {
1223 			if (strncmp(g_config.mos->netdev_table->ent[i]->dev_name, word, wlen) == 0) {
1224 				g_config.mos->netdev_table->ent[i]->stat_print = TRUE;
1225 			}
1226 		}
1227 		str = word + wlen;
1228 	}
1229 
1230 }
1231 /*----------------------------------------------------------------------------*/
1232 int
1233 LoadConfigurationUpperHalf(const char *fname)
1234 {
1235 	char *line;
1236 	int llen;
1237 
1238 	char *raw = ReadConf(fname);
1239 	char *preprocessed = PreprocessConf(raw);
1240 	int len = strlen(preprocessed);
1241 
1242 	InitConfig(&g_config);
1243 
1244 	LINE_FOREACH(line, llen, preprocessed, len) {
1245 		struct conf_block *nblk;
1246 
1247 		if ((nblk = DetectBlock(NULL, line, len - (line - preprocessed)))) {
1248 			ParseBlock(nblk);
1249 			/* skip parsed conf_block by fast forwarding line */
1250 			line = &nblk->buf[nblk->len] + 1;
1251 			llen = 0;
1252 		}
1253 	}
1254 
1255 	CheckConfValidity(&g_config);
1256 
1257 	PatchCONFIG(&g_config);
1258 
1259 	//PrintConf(&g_config);
1260 
1261 	return 0;
1262 }
1263 /*----------------------------------------------------------------------------*/
1264 void
1265 LoadConfigurationLowerHalf(void)
1266 {
1267 	struct route_conf *route_conf = g_config.mos->route_table;
1268 	struct netdev_conf *netdev_conf = g_config.mos->netdev_table;
1269 	struct nic_forward_conf *nicfwd_conf = g_config.mos->nic_forward_table;
1270 	struct route_entry *rwalk;
1271 	struct netdev_entry *nwalk;
1272 	struct nic_forward_entry *fwalk;
1273 	int nif_in = -1;
1274 	int nif_out = -1;
1275 
1276 	TAILQ_FOREACH(rwalk, &route_conf->list, link) {
1277 		TAILQ_FOREACH(nwalk, &netdev_conf->list, link) {
1278 			if (!strcmp(nwalk->dev_name, rwalk->dev_name))
1279 				break;
1280 		}
1281 		if (!nwalk)
1282 			continue;
1283 		if (nwalk->ifindex < 0 &&
1284 			(nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr)) < 0) {
1285 			TRACE_ERROR("Interface '%s' not found\n", nwalk->dev_name);
1286 			exit(EXIT_FAILURE);
1287 		}
1288 
1289 		rwalk->nif = nwalk->ifindex;
1290 	}
1291 
1292 	if (nicfwd_conf != NULL) {
1293 		TAILQ_FOREACH(fwalk, &nicfwd_conf->list, link) {
1294 			TAILQ_FOREACH(nwalk, &netdev_conf->list, link) {
1295 				if (!strcmp(nwalk->dev_name, fwalk->nif_in))
1296 					nif_in = nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr);
1297 				if (!strcmp(nwalk->dev_name, fwalk->nif_out))
1298 					nif_out = nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr);
1299 			}
1300 
1301 			if (nif_in != -1)
1302 				nicfwd_conf->nic_fwd_table[nif_in] = nif_out;
1303 			if (nif_out != -1)
1304 				nicfwd_conf->nic_fwd_table[nif_out] = nif_in;
1305 			nif_in = nif_out = -1;
1306 		}
1307 	}
1308 }
1309 /*----------------------------------------------------------------------------*/
1310 void
1311 FreeConfigResources()
1312 {
1313 	if (file) {
1314 		free(file);
1315 		file = NULL;
1316 	}
1317 }
1318 /*----------------------------------------------------------------------------*/
1319