xref: /mOS-networking-stack/core/src/config.c (revision 1879243c)
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 = mystrtol(sample, 10);
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-1);
250 	ent->ifr.ifr_name[IFNAMSIZ-1] = '\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 		exit(EXIT_FAILURE);
340 	}
341 
342 	/* getting address */
343 	if (ioctl(sock, SIOCGIFADDR, &ent->ifr) == 0 ) {
344 		struct in_addr sin = ((struct sockaddr_in *)&ent->ifr.ifr_addr)->sin_addr;
345 		ent->ip_addr = *(uint32_t *)&sin;
346 	}
347 
348 	/* Net MASK */
349 	if (ioctl(sock, SIOCGIFNETMASK, &ent->ifr) == 0) {
350 		struct in_addr sin = ((struct sockaddr_in *)&ent->ifr.ifr_addr)->sin_addr;
351 		ent->netmask = *(uint32_t *)&sin;
352 	}
353 
354 #ifdef DARWIN
355 	/* FIXME: How can I retrieve a mac address in MAC OS? */
356 #else
357 	if (ioctl(sock, SIOCGIFHWADDR, &ent->ifr) == 0 ) {
358 		for (i = 0; i < 6; i ++) {
359 			ent->haddr[i] = ent->ifr.ifr_addr.sa_data[i];
360 		}
361 	}
362 #endif
363 
364 	close(sock);
365 
366 	ent->ifindex = -1;
367 
368 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
369 	conf->ent[conf->num] = ent;
370 	conf->num++;
371 }
372 /*----------------------------------------------------------------------------*/
373 static void
374 FeedArpConfLine(struct conf_block *blk, char *line, int len)
375 {
376 	struct arp_conf * const conf = (struct arp_conf *)blk->conf;
377 
378 	char address[WORD_LEN];
379 	int prefix;
380 	uint8_t haddr[ETH_ALEN] = {0};
381 
382 	/* skip first space */
383 	while (isspace(*line))
384 		line++, len--;
385 
386 	if (sscanf(line, "%[0-9.]/%d %hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
387 				address, &prefix, &haddr[0], &haddr[1], &haddr[2],
388 				&haddr[3], &haddr[4], &haddr[5]) != 8)
389 		return;
390 
391 	struct _arp_entry *ent = calloc(1, sizeof(struct _arp_entry));
392 	if (!ent) {
393 		TRACE_ERROR("Could not allocate memory for arp_entry!\n");
394 		exit(EXIT_FAILURE);
395 	}
396 
397 	ent->ip = inet_addr(address);
398 	ent->prefix = prefix;
399 	ent->mask = htonl((prefix == 0) ? 0 : ((-1) << (32 - prefix)));
400 	ent->masked_ip = ent->mask & ent->ip;
401 	memcpy(ent->haddr, haddr, ETH_ALEN);
402 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
403 	conf->ent[conf->num] = ent;
404 	conf->num++;
405 }
406 /*----------------------------------------------------------------------------*/
407 static void
408 FeedRouteConfLine(struct conf_block *blk, char *line, int len)
409 {
410 	struct route_conf * const conf = (struct route_conf *)blk->conf;
411 
412 	char address[WORD_LEN], dev_name[WORD_LEN];
413 	int prefix;
414 
415 	/* skip first space */
416 	while (isspace(*line))
417 		line++, len--;
418 
419 	if (sscanf(line, "%[0-9.]/%d %[^ ^\n^\t]", address, &prefix, dev_name) != 3)
420 		return;
421 
422 	struct route_entry *ent = calloc(1, sizeof(struct route_entry));
423 	if (!ent) {
424 		TRACE_ERROR("Could not allocate memory for route_entry!\n");
425 		exit(EXIT_FAILURE);
426 	}
427 
428 	ent->ip = inet_addr(address);
429 	ent->mask = htonl((prefix == 0) ? 0 : ((-1) << (32 - prefix)));
430 	ent->masked_ip = ent->mask & ent->ip;
431 	ent->prefix = prefix;
432 	ent->nif = -1;
433 	strcpy(ent->dev_name, dev_name);
434 
435 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
436 	conf->ent[conf->num] = ent;
437 	conf->num++;
438 }
439 /*----------------------------------------------------------------------------*/
440 static void
441 FeedNICFwdConfLine(struct conf_block *blk, char *line, int len)
442 {
443 	struct nic_forward_conf * const conf = (struct nic_forward_conf *)blk->conf;
444 	char dev_name_in[WORD_LEN];
445 	char dev_name_out[WORD_LEN];
446 
447 	/* skip first space */
448 	while (isspace(*line))
449 		line++, len--;
450 
451 	if (sscanf(line, "%[^ ^\n^\t] %[^ ^\n^\t]", dev_name_in, dev_name_out) != 2)
452 		return;
453 
454 	struct nic_forward_entry *ent = calloc(1, sizeof(struct nic_forward_entry));
455 	if (!ent) {
456 		TRACE_ERROR("Could not allocate memory for nic forward entry!\n");
457 		exit(EXIT_FAILURE);
458 	}
459 
460 	strcpy(ent->nif_in, dev_name_in);
461 	strcpy(ent->nif_out, dev_name_out);
462 	TAILQ_INSERT_TAIL(&conf->list, ent, link);
463 	conf->ent[conf->num] = ent;
464 	conf->num++;
465 }
466 /*----------------------------------------------------------------------------*/
467 static void
468 MosConfAddChild(struct conf_block *blk, struct conf_block *child)
469 {
470 	struct mos_conf * const conf = (struct mos_conf *)blk->conf;
471 
472 	if (strcmp(child->name, NETDEV_BLOCK_NAME) == 0) {
473 		conf->netdev = child;
474 		conf->netdev_table = (struct netdev_conf *)child->conf;
475 	} else if (strcmp(child->name, ARP_BLOCK_NAME) == 0) {
476 		conf->arp = child;
477 		conf->arp_table = (struct arp_conf *)child->conf;
478 	} else if (strcmp(child->name, ROUTE_BLOCK_NAME) == 0) {
479 		conf->route = child;
480 		conf->route_table = (struct route_conf *)child->conf;
481 	} else if (strcmp(child->name, FORWARD_BLOCK_NAME) == 0) {
482 		conf->nic_forward = child;
483 		conf->nic_forward_table = (struct nic_forward_conf *)child->conf;
484 	} else
485 		return;
486 }
487 /*----------------------------------------------------------------------------*/
488 static int
489 AppConfIsValid(struct conf_block *blk)
490 {
491 	struct app_conf * const conf = (struct app_conf *)blk->conf;
492 
493 	if (conf->app_argc <= 0)
494 		return 0;
495 
496 	return 1;
497 }
498 /*----------------------------------------------------------------------------*/
499 static int
500 MosConfIsValid(struct conf_block *blk)
501 {
502 	return 1;
503 }
504 /*----------------------------------------------------------------------------*/
505 static int
506 NetdevConfIsValid(struct conf_block *blk)
507 {
508 	return 1;
509 }
510 /*----------------------------------------------------------------------------*/
511 static int
512 ArpConfIsValid(struct conf_block *blk)
513 {
514 	return 1;
515 }
516 /*----------------------------------------------------------------------------*/
517 static int
518 RouteConfIsValid(struct conf_block *blk)
519 {
520 	return 1;
521 }
522 /*----------------------------------------------------------------------------*/
523 static int
524 NICFwdConfIsValid(struct conf_block *blk)
525 {
526 	return 1;
527 }
528 /*----------------------------------------------------------------------------*/
529 static void
530 NetdevConfPrint(struct conf_block *blk)
531 {
532 	struct netdev_conf * const conf = (struct netdev_conf *)blk->conf;
533 
534 	printf(" +===== Netdev configuration (%d entries) =====\n",
535 			conf->num);
536 
537 	struct netdev_entry *walk;
538 	TAILQ_FOREACH(walk, &conf->list, link) {
539 		printf(" | %s(idx: %d, HADDR: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX) maps to CPU 0x%016lX\n",
540 				walk->dev_name, walk->ifindex,
541 				walk->haddr[0], walk->haddr[1], walk->haddr[2],
542 				walk->haddr[3], walk->haddr[4], walk->haddr[5],
543 				walk->cpu_mask);
544 	}
545 	printf(" |\n");
546 }
547 /*----------------------------------------------------------------------------*/
548 static void
549 ArpConfPrint(struct conf_block *blk)
550 {
551 	struct arp_conf * const conf = (struct arp_conf *)blk->conf;
552 
553 	printf(" +===== Static ARP table configuration (%d entries) =====\n",
554 			conf->num);
555 
556 	struct _arp_entry *walk;
557 	TAILQ_FOREACH(walk, &conf->list, link) {
558 		printf(" | IP: 0x%08X, NETMASK: 0x%08X, "
559 			   "HADDR: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX\n",
560 			   ntohl(walk->ip), ntohl(walk->mask),
561 			   walk->haddr[0], walk->haddr[1], walk->haddr[2],
562 			   walk->haddr[3], walk->haddr[4], walk->haddr[5]);
563 	}
564 	printf(" |\n");
565 }
566 /*----------------------------------------------------------------------------*/
567 static void
568 RouteConfPrint(struct conf_block *blk)
569 {
570 	struct route_conf * const conf = (struct route_conf *)blk->conf;
571 
572 	printf(" +===== Routing table configuration (%d entries) =====\n",
573 			conf->num);
574 
575 	struct route_entry *walk;
576 	TAILQ_FOREACH(walk, &conf->list, link) {
577 		printf(" | IP: 0x%08X, NETMASK: 0x%08X, INTERFACE: %s(idx: %d)\n",
578 			   ntohl(walk->ip), ntohl(walk->mask), walk->dev_name, walk->nif);
579 	}
580 	printf(" |\n");
581 }
582 /*----------------------------------------------------------------------------*/
583 static void
584 NICFwdConfPrint(struct conf_block *blk)
585 {
586 	int i;
587 	struct nic_forward_conf * const conf = (struct nic_forward_conf *)blk->conf;
588 
589 	printf(" +===== NIC Forwarding table configuration (%d entries) =====\n",
590 			conf->num);
591 
592 	struct nic_forward_entry *walk;
593 	TAILQ_FOREACH(walk, &conf->list, link) {
594 		printf(" | NIC Forwarding Entry: %s <---> %s",
595 		       walk->nif_in, walk->nif_out);
596 	}
597 	printf(" |\n");
598 
599 	printf(" | NIC Forwarding Index Table: |\n");
600 
601 	for (i = 0; i < MAX_FORWARD_ENTRY; i++)
602 		printf( " | %d --> %d | \n", i, conf->nic_fwd_table[i]);
603 }
604 /*----------------------------------------------------------------------------*/
605 static void
606 AppConfPrint(struct conf_block *blk)
607 {
608 	struct app_conf * const conf = (struct app_conf *)blk->conf;
609 
610 	printf("===== Application configuration =====\n");
611 	printf("| type:       %s\n", conf->type);
612 	printf("| run:        %s\n", conf->run);
613 	printf("| cpu_mask:   0x%016lX\n", conf->cpu_mask);
614 	printf("| ip_forward: %s\n", conf->ip_forward ? "forward" : "drop");
615 	printf("\n");
616 }
617 /*----------------------------------------------------------------------------*/
618 static void
619 MosConfPrint(struct conf_block *blk)
620 {
621 	struct mos_conf * const conf = (struct mos_conf *)blk->conf;
622 
623 	printf("===== MOS configuration =====\n");
624 	printf("| num_cores:       %d\n", conf->num_cores);
625 	printf("| nb_mem_channels: %d\n", conf->nb_mem_channels);
626 	printf("| max_concurrency: %d\n", conf->max_concurrency);
627 	printf("| rmem_size:       %d\n", conf->rmem_size);
628 	printf("| wmem_size:       %d\n", conf->wmem_size);
629 	printf("| tcp_tw_interval: %d\n", conf->tcp_tw_interval);
630 	printf("| tcp_timeout:     %d\n", conf->tcp_timeout);
631 	printf("| multiprocess:    %s\n", conf->multiprocess ? "true" : "false");
632 	printf("| mos_log:         %s\n", conf->mos_log);
633 	printf("| stat_print:      %s\n", conf->stat_print);
634 	printf("| forward:         %s\n", conf->forward ? "forward" : "drop");
635 	printf("|\n");
636 	if (conf->netdev)
637 		conf->netdev->print(conf->netdev);
638 	if (conf->arp)
639 		conf->arp->print(conf->arp);
640 	if (conf->route)
641 		conf->route->print(conf->route);
642 	if (conf->nic_forward)
643 		conf->nic_forward->print(conf->nic_forward);
644 	printf("\n");
645 }
646 /*----------------------------------------------------------------------------*/
647 static void
648 InitAppBlock(struct config *config, struct conf_block *blk)
649 {
650 	assert(blk);
651 
652 	blk->name = APP_BLOCK_NAME;
653 
654 	blk->feed = FeedAppConfLine;
655 	blk->addchild = NULL;
656 	blk->isvalid = AppConfIsValid;
657 	blk->print = AppConfPrint;
658 
659 	struct app_conf *conf = calloc(1, sizeof(struct app_conf));
660 	if (conf == NULL) {
661 		TRACE_ERROR("Could not allocate memory for app_conf!\n");
662 		exit(EXIT_FAILURE);
663 	}
664 	/* set default values */
665 	conf->cpu_mask = -1;
666 	conf->ip_forward = 1;
667 	conf->app_argc = 0;
668 	blk->conf = conf;
669 
670 	blk->list = (typeof(blk->list))&config->app_blkh;
671 }
672 /*----------------------------------------------------------------------------*/
673 static void
674 InitMosBlock(struct config *config, struct conf_block *blk)
675 {
676 	assert(blk);
677 
678 	blk->name = MOS_BLOCK_NAME;
679 
680 	blk->feed = FeedMosConfLine;
681 	blk->addchild = MosConfAddChild;
682 	blk->isvalid = MosConfIsValid;
683 	blk->print = MosConfPrint;
684 
685 	struct mos_conf *conf = calloc(1, sizeof(struct mos_conf));
686 	if (conf == NULL) {
687 		TRACE_ERROR("Could not allocate memory for mos_conf!\n");
688 		exit(EXIT_FAILURE);
689 	}
690 	/* set default values */
691 	conf->forward = 1;
692 	conf->nb_mem_channels = 0;
693 	conf->max_concurrency = 100000;
694 	conf->no_ring_buffers = 0;
695 	conf->rmem_size = 8192;
696 	conf->wmem_size = 8192;
697 	conf->tcp_tw_interval = SEC_TO_USEC(TCP_TIMEWAIT) / TIME_TICK;
698 	conf->tcp_timeout = SEC_TO_USEC(TCP_TIMEOUT) / TIME_TICK;
699 	conf->cpu_mask = 0;
700 	blk->conf = conf;
701 
702 	blk->list = (typeof(blk->list))&config->mos_blkh;
703 	config->mos = conf;
704 }
705 /*----------------------------------------------------------------------------*/
706 static void
707 InitNetdevBlock(struct config *config, struct conf_block *blk)
708 {
709 	assert(blk);
710 
711 	blk->name = NETDEV_BLOCK_NAME;
712 
713 	blk->feed = FeedNetdevConfLine;
714 	blk->addchild = NULL;
715 	blk->isvalid = NetdevConfIsValid;
716 	blk->print = NetdevConfPrint;
717 
718 	struct netdev_conf *conf = calloc(1, sizeof(struct netdev_conf));
719 	if (conf == NULL) {
720 		TRACE_ERROR("Could not allocate memory for netdev_conf!\n");
721 		exit(EXIT_FAILURE);
722 	}
723 	TAILQ_INIT(&conf->list);
724 	blk->conf = conf;
725 
726 	blk->list = NULL;
727 }
728 /*----------------------------------------------------------------------------*/
729 static void
730 FetchARPKernelEntries(struct arp_conf * const config)
731 {
732 #define	_PATH_PROCNET_ARP		"/proc/net/arp"
733 #define	DPDK_PREFIX			"dpdk"
734 #define DPDK_PREFIX_LEN			4
735 #define LINE_LEN			200
736 #define ENTRY_LEN			25
737 
738 	FILE *fp;
739 	char ip[ENTRY_LEN];
740 	char hwa[ENTRY_LEN];
741 	char mask[ENTRY_LEN];
742 	char dev[WORD_LEN];
743 	char line[LINE_LEN];
744 	int type, flags, num;
745 
746 	if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
747 		perror(_PATH_PROCNET_ARP);
748 		exit(EXIT_FAILURE);
749 	}
750 
751 	/* Bypass header -- read until newline */
752 	if (fgets(line, sizeof(line), fp) != (char *) NULL) {
753 		strcpy(mask, "-");
754 		strcpy(dev, "-");
755 		/* Read the ARP cache entries. */
756 		for (; fgets(line, sizeof(line), fp);) {
757 
758 			num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
759 				     ip, &type, &flags, hwa, mask, dev);
760 			if (num < 6)
761 				break;
762 
763 			/* if the user specified device differs, skip it */
764 			if (strncmp(dev, DPDK_PREFIX, DPDK_PREFIX_LEN))
765 				continue;
766 
767 			/* if the entry has not expired/tagged for removal then... */
768 			if (flags != 0x00) {
769 				/* add the new arp entry in MOS database */
770 				struct _arp_entry *ent = calloc(1, sizeof(struct _arp_entry));
771 				if (!ent) {
772 					TRACE_ERROR("Can't allocate memory for arp_entry\n");
773 					exit(EXIT_FAILURE);
774 				}
775 				uint8_t haddr[ETH_ALEN] = {0};
776 				if (sscanf(hwa, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
777 					   &haddr[0], &haddr[1], &haddr[2],
778 					   &haddr[3], &haddr[4], &haddr[5]) != 6) {
779 					TRACE_ERROR("Error reading the ARP entry\n");
780 					exit(EXIT_FAILURE);
781 				}
782 				ent->ip = inet_addr(ip);
783 				ent->prefix = 32;
784 				ent->mask = htonl((ent->prefix == 0) ? 0 : ((-1) << (32 - ent->prefix)));
785 				ent->masked_ip = ent->mask & ent->ip;
786 				memcpy(ent->haddr, haddr, ETH_ALEN);
787 				TAILQ_INSERT_TAIL(&config->list, ent, link);
788 				config->ent[config->num] = ent;
789 				config->num++;
790 			}
791 		}
792 	}
793 
794 	fclose(fp);
795 }
796 /*----------------------------------------------------------------------------*/
797 static void
798 FetchRouteKernelEntries(struct route_conf * const config)
799 {
800 #define	_PATH_PROCNET_ROUTE		"/proc/net/route"
801 #define	DPDK_PREFIX			"dpdk"
802 #define DPDK_PREFIX_LEN			4
803 
804 	FILE *fp;
805 	uint32_t gate;
806 	uint32_t dest;
807 	uint32_t mask;
808 	char dev[WORD_LEN];
809 	char line[LINE_LEN];
810 	char mtu[ENTRY_LEN];
811 	char win[ENTRY_LEN];
812 	char irtt[ENTRY_LEN];
813 	int flags, num, cnt, use, metric;
814 
815 	if ((fp = fopen(_PATH_PROCNET_ROUTE, "r")) == NULL) {
816 		perror(_PATH_PROCNET_ARP);
817 		exit(EXIT_FAILURE);
818 	}
819 
820 	/* Bypass header -- read until newline */
821 	if (fgets(line, sizeof(line), fp) != (char *) NULL) {
822 		/* Read the route table entries. */
823 		for (; fgets(line, sizeof(line), fp);) {
824 
825 			num = sscanf(line, "%s %08X %08X %d %d %d %d %08X %s %s %s\n",
826 				     dev,
827 				     &dest,
828 				     &gate,
829 				     &flags, &cnt, &use, &metric,
830 				     &mask,
831 				     mtu, win, irtt);
832 
833 			if (num < 11)
834 				break;
835 #if 0
836 			/* if the user specified device differs, skip it */
837 			if (strncmp(dev, DPDK_PREFIX, DPDK_PREFIX_LEN))
838 				continue;
839 #endif
840 			struct route_entry *ent = calloc(1, sizeof(struct route_entry));
841 			if (!ent) {
842 				TRACE_ERROR("Could not allocate memory for route_entry!\n");
843 				exit(EXIT_FAILURE);
844 			}
845 
846 			ent->ip = dest;
847 			ent->prefix = 32 - __builtin_clz(mask);
848 			ent->mask = mask;
849 			ent->masked_ip = ent->mask & ent->ip;
850 			strcpy(ent->dev_name, dev);
851 			TAILQ_INSERT_TAIL(&config->list, ent, link);
852 			config->ent[config->num] = ent;
853 			config->num++;
854 		}
855 	}
856 
857 	fclose(fp);
858 }
859 /*----------------------------------------------------------------------------*/
860 static void
861 InitArpBlock(struct config *config, struct conf_block *blk)
862 {
863 	assert(blk);
864 
865 	blk->name = ARP_BLOCK_NAME;
866 
867 	blk->feed = FeedArpConfLine;
868 	blk->addchild = NULL;
869 	blk->isvalid = ArpConfIsValid;
870 	blk->print = ArpConfPrint;
871 
872 	struct arp_conf *conf = calloc(1, sizeof(struct arp_conf));
873 	if (conf == NULL) {
874 		TRACE_ERROR("Could not allocate memory for arp_conf!\n");
875 		exit(EXIT_FAILURE);
876 	}
877 	TAILQ_INIT(&conf->list);
878 	blk->conf = conf;
879 
880 	blk->list = NULL;
881 	config->mos->arp = blk;
882 
883 	/* fetch relevant ARP entries for dpdk? from kernel tables */
884 	FetchARPKernelEntries(conf);
885 }
886 /*----------------------------------------------------------------------------*/
887 static void
888 InitRouteBlock(struct config *config, struct conf_block *blk)
889 {
890 	assert(blk);
891 
892 	blk->name = ROUTE_BLOCK_NAME;
893 
894 	blk->feed = FeedRouteConfLine;
895 	blk->addchild = NULL;
896 	blk->isvalid = RouteConfIsValid;
897 	blk->print = RouteConfPrint;
898 
899 	struct route_conf *conf = calloc(1, sizeof(struct route_conf));
900 	if (conf == NULL) {
901 		TRACE_ERROR("Could not allocate memory for route_conf!\n");
902 		exit(EXIT_FAILURE);
903 	}
904 	TAILQ_INIT(&conf->list);
905 	blk->conf = conf;
906 
907 	blk->list = NULL;
908 	config->mos->route = blk;
909 
910 	/* fetch relevant route entries for dpdk? from kernel tables */
911 	FetchRouteKernelEntries(conf);
912 }
913 /*----------------------------------------------------------------------------*/
914 static void
915 InitNICForwardBlock(struct config *config, struct conf_block *blk)
916 {
917 	int i;
918 	assert(blk);
919 	blk->name = FORWARD_BLOCK_NAME;
920 
921 	blk->feed = FeedNICFwdConfLine;
922 	blk->addchild = NULL;
923 	blk->isvalid = NICFwdConfIsValid;
924 	blk->print = NICFwdConfPrint;
925 
926 	struct nic_forward_conf *conf = calloc(1, sizeof(struct nic_forward_conf));
927 	if (conf == NULL) {
928 		TRACE_ERROR("Could not allocate memory for nic_forward_conf!\n");
929 		exit(EXIT_FAILURE);
930 	}
931 	for (i = 0; i < MAX_FORWARD_ENTRY; i++)
932 		conf->nic_fwd_table[i] = -1;
933 
934 	TAILQ_INIT(&conf->list);
935 	blk->conf = conf;
936 
937 	blk->list = NULL;
938 	config->mos->nic_forward = blk;
939 }
940 /*----------------------------------------------------------------------------*/
941 void
942 PrintConf(struct config *conf)
943 {
944 	struct conf_block *walk;
945 	TAILQ_FOREACH(walk, &conf->app_blkh, link) {
946 		if (walk->print)
947 			walk->print(walk);
948 	}
949 
950 	TAILQ_FOREACH(walk, &conf->mos_blkh, link) {
951 		if (walk->print)
952 			walk->print(walk);
953 	}
954 }
955 /*----------------------------------------------------------------------------*/
956 static void
957 CheckConfValidity(struct config *conf)
958 {
959 	struct conf_block *walk;
960 	TAILQ_FOREACH(walk, &conf->app_blkh, link) {
961 		if (!walk->isvalid || !walk->isvalid(walk))
962 			goto __error;
963 	}
964 
965 	TAILQ_FOREACH(walk, &conf->mos_blkh, link) {
966 		struct conf_block *child;
967 
968 		if (!walk->isvalid || !walk->isvalid(walk))
969 			goto __error;
970 
971 		child = ((struct mos_conf *)walk->conf)->netdev;
972 		if (!child->isvalid || !child->isvalid(child))
973 			goto __error;
974 
975 		child = ((struct mos_conf *)walk->conf)->arp;
976 		if (!child->isvalid || !child->isvalid(child))
977 			goto __error;
978 
979 		child = ((struct mos_conf *)walk->conf)->route;
980 		if (!child->isvalid || !child->isvalid(child))
981 			goto __error;
982 	}
983 
984 	return;
985 
986 __error:
987 	printf("!!!!! Configuration validity check failure !!!!!\n");
988 	if (walk && walk->print)
989 		walk->print(walk);
990 	exit(0);
991 }
992 /*----------------------------------------------------------------------------*/
993 static char *
994 ReadConf(const char *fname)
995 {
996 	size_t hav_read = 0, rc;
997 	FILE *fp = fopen(fname, "r");
998 	if (fp == NULL) {
999 		TRACE_ERROR("Cannot open the config file %s\n", fname);
1000 		exit(-1);
1001 	}
1002 
1003 	/* find out the size of file */
1004 	fseek(fp, 0L, SEEK_END);
1005 	int size = ftell(fp);
1006 	fseek(fp, 0L, SEEK_SET);
1007 
1008 	file = calloc(1, size + 1);
1009 	if (file == NULL) {
1010 		TRACE_ERROR("Can't allocate memory for file!\n");
1011 		exit(EXIT_FAILURE);
1012 	}
1013 
1014 	file[size] = '\0';
1015 
1016 	while (hav_read < size) {
1017 		rc = fread(file, 1, size, fp);
1018 		/* sanity check */
1019 		if (rc <= 0) break;
1020 		hav_read += rc;
1021 	}
1022 
1023 	fclose(fp);
1024 
1025 	return file;
1026 }
1027 /*----------------------------------------------------------------------------*/
1028 static char *
1029 PreprocessConf(char *raw)
1030 {
1031 	char *line;
1032 	int llen;
1033 
1034 	int len = strlen(raw);
1035 
1036 	LINE_FOREACH(line, llen, raw, len) {
1037 		int i, iscomment = 0;
1038 		for (i = 0; i < llen; i++) {
1039 			if (!iscomment && line[i] == '#')
1040 				iscomment = 1;
1041 			if (iscomment)
1042 				line[i] = ' ';
1043 		}
1044 	}
1045 	return raw;
1046 }
1047 /*----------------------------------------------------------------------------*/
1048 static void
1049 InitConfig(struct config *config)
1050 {
1051 	int i;
1052 	struct conf_block *blk;
1053 
1054 	TAILQ_INIT(&g_free_blkh);
1055 	TAILQ_INIT(&config->app_blkh);
1056 	TAILQ_INIT(&config->mos_blkh);
1057 
1058 	for (i = 0; i < MAX_APP_BLOCK; i++) {
1059 		/* Allocate app conf_block */
1060 		blk = calloc(1, sizeof(struct conf_block));
1061 		if (blk == NULL) goto init_config_err;
1062 		InitAppBlock(config, blk);
1063 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1064 
1065 		/* Allocate netdev conf_block */
1066 		blk = calloc(1, sizeof(struct conf_block));
1067 		if (blk == NULL) goto init_config_err;
1068 		InitNetdevBlock(config, blk);
1069 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1070 	}
1071 
1072 	for (i = 0; i < MAX_MOS_BLOCK; i++) {
1073 		/* Allocate mos conf_block */
1074 		blk = calloc(1, sizeof(struct conf_block));
1075 		if (blk == NULL) goto init_config_err;
1076 		InitMosBlock(config, blk);
1077 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1078 
1079 		/* Allocate arp conf_block */
1080 		blk = calloc(1, sizeof(struct conf_block));
1081 		if (blk == NULL) goto init_config_err;
1082 		InitArpBlock(config, blk);
1083 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1084 
1085 		/* Allocate route conf_block */
1086 		blk = calloc(1, sizeof(struct conf_block));
1087 		if (blk == NULL) goto init_config_err;
1088 		InitRouteBlock(config, blk);
1089 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1090 
1091 		/* Allocate nic_forward conf_block */
1092 		blk = calloc (1, sizeof(struct conf_block));
1093 		if (blk == NULL) goto init_config_err;
1094 		InitNICForwardBlock(config, blk);
1095 		TAILQ_INSERT_TAIL(&g_free_blkh, blk, link);
1096 	}
1097 	return;
1098  init_config_err:
1099 	TRACE_ERROR("Can't allocate memory for blk_entry!\n");
1100 	exit(EXIT_FAILURE);
1101 }
1102 /*----------------------------------------------------------------------------*/
1103 static struct conf_block *
1104 AllocateBlock(char *name, int len)
1105 {
1106 	struct conf_block *walk, *tmp;
1107 
1108 	for (walk = TAILQ_FIRST(&g_free_blkh); walk != NULL; walk = tmp) {
1109 		tmp = TAILQ_NEXT(walk, link);
1110 		if (len == strlen(walk->name) && strncmp(walk->name, name, len) == 0) {
1111 			TAILQ_REMOVE(&g_free_blkh, walk, link);
1112 			if (walk->list)
1113 				TAILQ_INSERT_TAIL(walk->list, walk, link);
1114 			return walk;
1115 		}
1116 	}
1117 
1118 	return NULL;
1119 }
1120 /*----------------------------------------------------------------------------*/
1121 struct conf_block *
1122 DetectBlock(struct conf_block *blk, char *buf, int len)
1123 {
1124 	int depth = 0;
1125 	char *blkname = NULL, *end = &buf[len];
1126 	int blknamelen;
1127 	struct conf_block *nblk;
1128 
1129 	/* skip first space */
1130 	while (buf < end && isspace(*buf))
1131 		buf++;
1132 
1133 	if (DetectWord(buf, len, &blkname, &blknamelen) < 0
1134 			|| blkname != buf)
1135 		/* Failed to detect conf_block name */
1136 		return NULL;
1137 
1138 	/* fast forward buffer */
1139 	buf += blknamelen;
1140 
1141 	/* skip space */
1142 	while (buf < end && isspace(*buf))
1143 		buf++;
1144 
1145 	/* buf must be '{' */
1146 	if (buf >= end || *buf != '{')
1147 		return NULL;
1148 
1149 	buf++;   /* skip '{' */
1150 	while (buf < end && isspace(*buf))
1151 		buf++; /* skip space */
1152 	depth++; /* Now in first parenthesis */
1153 
1154 	/* Now, the `buf` points the first byte inside conf_block */
1155 
1156 	for (len = 0; &buf[len] < end; len++) {
1157 		if (buf[len] == '{')
1158 			depth++;
1159 		else if (buf[len] == '}' && --depth == 0)
1160 				break;
1161 	}
1162 
1163 	if (depth != 0)
1164 		/* Failed to find the end of parenthesis */
1165 		return NULL;
1166 
1167 	if (!(nblk = AllocateBlock(blkname, blknamelen)))
1168 		return NULL;
1169 
1170 	if (blk) {
1171 		assert(blk->addchild);
1172 		blk->addchild(blk, nblk);
1173 	}
1174 
1175 	nblk->buf = buf;
1176 	nblk->len = len;
1177 
1178 	return nblk;
1179 }
1180 /*----------------------------------------------------------------------------*/
1181 static void
1182 ParseBlock(struct conf_block *blk)
1183 {
1184 	char *line;
1185 	int llen;
1186 
1187 	LINE_FOREACH(line, llen, blk->buf, blk->len) {
1188 		struct conf_block *nblk;
1189 
1190 		if ((nblk = DetectBlock(blk, line, blk->len - (line - blk->buf)))) {
1191 			ParseBlock(nblk);
1192 			/* skip nested conf_block by fast forwarding line */
1193 			line = &nblk->buf[nblk->len] + 1;
1194 			llen = 0;
1195 		} else
1196 			blk->feed(blk, line, llen);
1197 	}
1198 }
1199 /*----------------------------------------------------------------------------*/
1200 void
1201 PatchCONFIG(struct config *config)
1202 {
1203 	int i;
1204 	char *word, *str, *end;
1205 	int wlen;
1206 
1207 	g_config.mos->num_cores = num_cpus;
1208 	word = NULL;
1209 
1210 	i = 0;
1211 	struct conf_block *bwalk;
1212 	TAILQ_FOREACH(bwalk, &g_config.app_blkh, link) {
1213 		struct app_conf *app_conf = (struct app_conf *)bwalk->conf;
1214 		g_config.mos->forward = g_config.mos->forward && app_conf->ip_forward;
1215 		if (end_app_exists == 0 && !strcmp(app_conf->type, "end"))
1216 			end_app_exists = 1;
1217 		if (mon_app_exists == 0 && !strcmp(app_conf->type, "monitor"))
1218 			mon_app_exists = 1;
1219 		i++;
1220 	}
1221 	/* turn on monitor mode if end app is not set */
1222 	if (!end_app_exists && !mon_app_exists) mon_app_exists = 1;
1223 
1224 	/* stat print */
1225 	str = g_config.mos->stat_print;
1226 	end = str + strlen(str);
1227 	while (DetectWord(str, end - str, &word, &wlen) == 0) {
1228 		for (i = 0; i < g_config.mos->netdev_table->num; i++) {
1229 			if (strncmp(g_config.mos->netdev_table->ent[i]->dev_name, word, wlen) == 0) {
1230 				g_config.mos->netdev_table->ent[i]->stat_print = TRUE;
1231 			}
1232 		}
1233 		str = word + wlen;
1234 	}
1235 
1236 }
1237 /*----------------------------------------------------------------------------*/
1238 int
1239 LoadConfigurationUpperHalf(const char *fname)
1240 {
1241 	char *line;
1242 	int llen;
1243 
1244 	char *raw = ReadConf(fname);
1245 	char *preprocessed = PreprocessConf(raw);
1246 	int len = strlen(preprocessed);
1247 
1248 	InitConfig(&g_config);
1249 
1250 	LINE_FOREACH(line, llen, preprocessed, len) {
1251 		struct conf_block *nblk;
1252 
1253 		if ((nblk = DetectBlock(NULL, line, len - (line - preprocessed)))) {
1254 			ParseBlock(nblk);
1255 			/* skip parsed conf_block by fast forwarding line */
1256 			line = &nblk->buf[nblk->len] + 1;
1257 			llen = 0;
1258 		}
1259 	}
1260 
1261 	CheckConfValidity(&g_config);
1262 
1263 	PatchCONFIG(&g_config);
1264 
1265 	//PrintConf(&g_config);
1266 
1267 	return 0;
1268 }
1269 /*----------------------------------------------------------------------------*/
1270 void
1271 LoadConfigurationLowerHalf(void)
1272 {
1273 	struct route_conf *route_conf = g_config.mos->route_table;
1274 	struct netdev_conf *netdev_conf = g_config.mos->netdev_table;
1275 	struct nic_forward_conf *nicfwd_conf = g_config.mos->nic_forward_table;
1276 	struct route_entry *rwalk;
1277 	struct netdev_entry *nwalk;
1278 	struct nic_forward_entry *fwalk;
1279 	int nif_in = -1;
1280 	int nif_out = -1;
1281 
1282 	TAILQ_FOREACH(rwalk, &route_conf->list, link) {
1283 		TAILQ_FOREACH(nwalk, &netdev_conf->list, link) {
1284 			if (!strcmp(nwalk->dev_name, rwalk->dev_name))
1285 				break;
1286 		}
1287 		if (!nwalk)
1288 			continue;
1289 		if (nwalk->ifindex < 0 &&
1290 			(nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr)) < 0) {
1291 			TRACE_ERROR("Interface '%s' not found\n", nwalk->dev_name);
1292 			exit(EXIT_FAILURE);
1293 		}
1294 
1295 		rwalk->nif = nwalk->ifindex;
1296 	}
1297 
1298 	if (nicfwd_conf != NULL) {
1299 		TAILQ_FOREACH(fwalk, &nicfwd_conf->list, link) {
1300 			TAILQ_FOREACH(nwalk, &netdev_conf->list, link) {
1301 				if (!strcmp(nwalk->dev_name, fwalk->nif_in))
1302 					nif_in = nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr);
1303 				if (!strcmp(nwalk->dev_name, fwalk->nif_out))
1304 					nif_out = nwalk->ifindex = current_iomodule_func->get_nif(&nwalk->ifr);
1305 			}
1306 
1307 			if (nif_in != -1)
1308 				nicfwd_conf->nic_fwd_table[nif_in] = nif_out;
1309 			if (nif_out != -1)
1310 				nicfwd_conf->nic_fwd_table[nif_out] = nif_in;
1311 			nif_in = nif_out = -1;
1312 		}
1313 	}
1314 }
1315 /*----------------------------------------------------------------------------*/
1316 void
1317 FreeConfigResources()
1318 {
1319 	if (file) {
1320 		free(file);
1321 		file = NULL;
1322 	}
1323 }
1324 /*----------------------------------------------------------------------------*/
1325