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