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