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