/*---------------------------------------------------------------------*/ static int loadline(lua_State *L) { TRACE_LUA_FUNC_START(); int status; lua_settop(L, 0); if (!pushline(L, 1)) { TRACE_LUA_FUNC_END(); return -1; /* no input */ } for (;;) { /* repeat until gets a complete line */ status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); if (!incomplete(L, status)) break; /* cannot try to add lines? */ if (!pushline(L, 0)) {/* no more input? */ TRACE_LUA_FUNC_END(); return -1; } lua_pushliteral(L, "\n"); /* add a new line... */ lua_insert(L, -2); /* ...between the two lines */ lua_concat(L, 3); /* join them */ } TRACE_DEBUG_LOG("%s\n", lua_tostring(L, 1)); TRACE_LUA_FUNC_END(); return status; }
/** * XXX - This function needs to be improved... */ static int linker_new(lua_State *L) { TRACE_LUA_FUNC_START(); int arg = -1; int nargs = lua_gettop(L); const char *brick_name = luaL_optstring(L, 1, 0); int i; if (nargs == 2) { arg = luaL_optint(L, 2, 0); } Linker_Intf *linker = push_linker(L); for (i = 3; elibs[i].init != NULL; i++) { if (!strcmp(elibs[i].getId(), brick_name)) linker->type = i; } linker->hash_split = arg; TRACE_DEBUG_LOG("Hash splitting logic: %d\n", linker->hash_split); linker->output_count = 0; linker->input_count = 0; linker->next_linker = NULL; TRACE_LUA_FUNC_END(); return 1; }
/*---------------------------------------------------------------------*/ int connect_to_bricks_server(char *rshell_args) { TRACE_BACKEND_FUNC_START(); int sock; struct sockaddr_in server; char *ip_addr, *port_str; uint16_t port; if (rshell_args == NULL) ip_addr = port_str = NULL; else { /* first parse the ipaddr and port string */ ip_addr = strtok(rshell_args, ":"); port_str = strtok(NULL, ":"); } port = (port_str == NULL) ? BRICKS_LISTEN_PORT : atoi(port_str); /* Create socket */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { TRACE_ERR("Could not create socket: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); return -1; } TRACE_DEBUG_LOG("Socket created"); server.sin_addr.s_addr = (ip_addr == NULL) ? inet_addr("127.0.0.1") : inet_addr(ip_addr); server.sin_family = AF_INET; server.sin_port = htons(port); /* Connect to remote server */ if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) { TRACE_ERR("Connect failed!: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); return -1; } TRACE_DEBUG_LOG("Connected\n"); TRACE_BACKEND_FUNC_END(); return sock; }
/** * Overloaded garbage collector */ static int linker_gc(lua_State *L) { TRACE_LUA_FUNC_START(); TRACE_DEBUG_LOG("Wiping off Linker: %p\n", to_linker(L, 1)); TRACE_LUA_FUNC_END(); UNUSED(L); return 0; }
/** * Overloaded garbage collector */ static int pkteng_gc(lua_State *L) { TRACE_LUA_FUNC_START(); TRACE_DEBUG_LOG("Wiping off PktEngine: %p\n", to_pkteng(L, 1)); TRACE_LUA_FUNC_END(); UNUSED(L); return 0; }
/** * Initializes all the modules of the system */ static inline void init_modules() { TRACE_FUNC_START(); TRACE_DEBUG_LOG("Initializing the engines module \n"); pktengine_init(); interface_init(); initBricks(); TRACE_FUNC_END(); }
/*---------------------------------------------------------------------*/ static int luaopen_platform(lua_State *L) { /* load systems' lua interface */ TRACE_LUA_FUNC_START(); platform_dir_create_meta(L); TRACE_DEBUG_LOG("%s", "Loading "PLATFORM_NAME" command metatable\n"); luaL_openlib(L, PLATFORM_NAME, platformlib, 0); platform_set_info(L); TRACE_LUA_FUNC_END(); return 1; }
/** * XXX - This function needs to be revised.. * Services incoming request from userland applications and takes * necessary actions. The actions can be: (i) passing packets to userland * apps etc. */ static void process_request_backend(engine *eng, struct kevent chlist[]) { TRACE_BACKEND_FUNC_START(); int client_sock, c, total_read, fd; struct sockaddr_in client; int read_size; char client_message[2000]; req_block *rb; char channelname[20]; total_read = read_size = 0; /* accept connection from an incoming client */ client_sock = accept(eng->listen_fd, (struct sockaddr *)&client, (socklen_t *)&c); if (client_sock < 0) { TRACE_LOG("accept failed: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); return; } /* Receive a message from client */ while ((read_size = recv(client_sock, &client_message[total_read], sizeof(req_block) - total_read, 0)) > 0) { total_read += read_size; if ((unsigned)total_read >= sizeof(req_block)) break; } TRACE_DEBUG_LOG("Total bytes read from listening socket: %d\n", total_read); /* parse new rule */ rb = (req_block *)client_message; TRACE_DEBUG_LOG("Got a new rule\n"); TRACE_DEBUG_LOG("Target: %d\n", rb->t); TRACE_DEBUG_LOG("TargetArgs.pid: %d\n", rb->targs.pid); TRACE_DEBUG_LOG("TargetArgs.proc_name: %s\n", rb->targs.proc_name); TRACE_FLUSH(); //snprintf(channelname, 20, "vale%s%d:s", // rb->targs.proc_name, rb->targs.pid); snprintf(channelname, 20, "%s%d", rb->targs.proc_name, rb->targs.pid); Rule *r = add_new_rule(eng, NULL, rb->t); /* create communication back channel */ fd = eng->iom.create_channel(eng, r, channelname/*, client_sock*/); EV_SET(&chlist[fd], fd, EVFILT_READ | EVFILT_WRITE, EV_ADD, 0, 0, NULL); /* add client sock to the polling layer */ fd = client_sock; EV_SET(&chlist[fd], fd, EVFILT_READ | EVFILT_WRITE, EV_ADD, 0, 0, NULL); /* continue listening */ fd = eng->listen_fd; EV_SET(&chlist[fd], fd, EVFILT_READ | EVFILT_WRITE, EV_ADD, 0, 0, NULL); TRACE_BACKEND_FUNC_END(); return; }
/** * Main entry point */ int main(int argc, char **argv) { TRACE_FUNC_START(); int rc; /* accept command-line arguments */ while ( (rc = getopt(argc, argv, "a:b:hsdf:")) != -1) { switch(rc) { case 'a': pc_info.rshell_args = (int8_t *)strdup(optarg); if (NULL == pc_info.rshell_args) { TRACE_ERR("Can't strdup remote shell args!!\n"); } break; case 'b': pc_info.batch_size = atoi(optarg); TRACE_DEBUG_LOG("Taking batch_size as %d\n", pc_info.batch_size); break; case 'd': pc_info.daemonize = 1; break; case 'h': print_help(*argv); break; case 'f': pc_info.lua_startup_file = (uint8_t *)strdup(optarg); if (NULL == pc_info.lua_startup_file) { TRACE_ERR("Can't strdup string for lua_startup_file: %s\n", strerror(errno)); } TRACE_DEBUG_LOG("Taking file %s as startup\n", pc_info.lua_startup_file); load_lua_file(optarg); break; case 's': pc_info.rshell = 1; break; default: print_help(*argv); break; } } /* init_modules */ init_modules(); /* check if rshell and daemonize are both enabled */ if (pc_info.daemonize && pc_info.rshell) { fprintf(stdout, "You cannot create a daemon process and " "a remote shell at the same time!\n"); fflush(stdout); print_help(*argv); return EXIT_FAILURE; } /* warp to remote shell, if asked */ if (pc_info.rshell) { if (pc_info.rshell_args == NULL) fprintf(stdout, "Using localhost and port %d by default\n", BRICKS_LISTEN_PORT); lua_kickoff(LUA_EXE_REMOTE_SHELL, pc_info.rshell_args); return EXIT_SUCCESS; } /* daemonize, if asked */ if ((pc_info.daemonize && (rc=do_daemonize()) == 0) || !pc_info.daemonize) { if (mark_pid_file(pv.pid_file) != 0) { TRACE_FUNC_END(); TRACE_ERR("Can't lock the pid file.\n" "Is a previous bricks daemon already running??\n"); } export_global_socket(); lua_kickoff((pc_info.daemonize) ? LUA_EXE_SCRIPT : LUA_EXE_HOME_SHELL, NULL); } /* initialize file printing mini-module */ print_status_file(); /* * if the user wants to daemonize and the process * is the child, then jump to accepting requests... */ if (pc_info.daemonize && rc == 0) { start_listening_reqs(); } TRACE_FUNC_END(); clean_exit(EXIT_SUCCESS); /* control will never come here */ return EXIT_SUCCESS; }
/** * XXX - This function is being revised * Services incoming request from userland applications and takes * necessary actions. The actions can be: (i) passing packets to userland * apps etc. */ static void process_request_backend(engine *eng, int epoll_fd) { TRACE_BACKEND_FUNC_START(); int client_sock, c, total_read; struct sockaddr_in client; int read_size; char client_message[2000]; struct epoll_event ev; req_block *rb; resp_block respb; total_read = read_size = 0; respb.len = sizeof(resp_block); /* accept connection from an incoming client */ client_sock = accept(eng->listen_fd, (struct sockaddr *)&client, (socklen_t *)&c); if (client_sock < 0) { TRACE_LOG("accept failed: %s\n", strerror(errno)); TRACE_BACKEND_FUNC_END(); return; } /* Receive a message from client */ while ((read_size = recv(client_sock, &client_message[total_read], sizeof(req_block) - total_read, 0)) > 0) { total_read += read_size; if ((unsigned)total_read >= sizeof(req_block)) break; } TRACE_DEBUG_LOG("Total bytes read from listening socket: %d\n", total_read); /* parse new rule */ rb = (req_block *)client_message; TRACE_DEBUG_LOG("Got a new request\n"); TRACE_DEBUG_LOG("\tLen: %u\n", rb->len); TRACE_DEBUG_LOG("\tInterface name: %s\n", rb->ifname); TRACE_FLUSH(); #if 0 respb.flag = (process_filter_request(eng, rb->ifname, &rb->f) == -1) ? 0 : 1; #else (void)rb; respb.flag = 1; #endif /* write the response back to the app */ if (write(client_sock, &respb, sizeof(respb)) == -1) { TRACE_LOG("Write failed due to %s\n", strerror(errno)); } /* add client sock to the polling layer */ ev.data.fd = client_sock; ev.events = EPOLLIN | EPOLLOUT; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { TRACE_LOG("Engine %s failed to exe epoll_ctl for fd: %d\n", eng->name, epoll_fd); TRACE_BACKEND_FUNC_END(); return; } /* for the moment, close the client socket immediately */ close(client_sock); /* continue listening */ ev.data.fd = eng->listen_fd; ev.events = EPOLLIN | EPOLLOUT; if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) { TRACE_LOG("Engine %s failed to exe epoll_ctl for fd: %d\n", eng->name, epoll_fd); TRACE_BACKEND_FUNC_END(); return; } TRACE_BACKEND_FUNC_END(); return; }
/*---------------------------------------------------------------------*/ static int pkteng_link(lua_State *L) { TRACE_LUA_FUNC_START(); PktEngine_Intf *pe = check_pkteng(L, 1); Linker_Intf *linker; Brick *first_brick; int nargs = lua_gettop(L); int i; /* check if args2 is user-data */ luaL_checktype(L, 2, LUA_TUSERDATA); /* Retrieve linker data */ linker = (Linker_Intf *)luaL_optudata(L, 2); /* set values as default */ pe->batch = DEFAULT_BATCH_SIZE; pe->qid = -1; /* if 3rd arg is passed, fill it with batch size */ if (nargs >= 3) pe->batch = luaL_checkint(L, 3); /* if 4th arg is passed, fill it with qid */ if (nargs >= 4) pe->qid = luaL_checkint(L, 4); lua_settop(L, 1); TRACE_DEBUG_LOG("Engine info so far...:\n" "\tName: %s\n" "\tCpu: %d\n" "\tBatch: %d\n" "\tQid: %d\n", pe->eng_name, pe->cpu, pe->batch, pe->qid); for (i = 0; i < linker->input_count; i++) { /* link the source(s) with the packet engine */ pktengine_link_iface((uint8_t *)pe->eng_name, (uint8_t *)linker->input_link[i], pe->batch, pe->qid); TRACE_LOG("Linking %s with link %s with batch size: %d and qid: %d\n", pe->eng_name, linker->input_link[i], pe->batch, pe->qid); } first_brick = createBrick(linker->type); if (first_brick == NULL) { TRACE_LUA_FUNC_END(); return 1; } first_brick->eng = engine_find((unsigned char *)pe->eng_name); first_brick->elib->init(first_brick, linker); if (first_brick->eng == NULL) { TRACE_LOG("Could not find engine with name: %s\n", pe->eng_name); TRACE_LUA_FUNC_END(); free(first_brick); return 1; } first_brick->elib->link(first_brick, linker); /* if there are pipelines, link them as well */ while (linker->next_linker != NULL) { linker = linker->next_linker; first_brick->elib->link(first_brick, linker); } TRACE_LUA_FUNC_END(); return 1; }
/*---------------------------------------------------------------------*/ int32_t netmap_link_iface(void *ctxt, const unsigned char *iface, const uint16_t batchsize, int8_t qid) { TRACE_NETMAP_FUNC_START(); char nifname[MAX_IFNAMELEN]; netmap_module_context *nmc = (netmap_module_context *)ctxt; netmap_iface_context *nic = NULL; /* setting nm-ifname*/ sprintf(nifname, "netmap:%s", iface); /* check if the interface has been registered with some other engine */ netiface *nif = interface_find((char *)iface); if (nif == NULL) { nic = calloc(1, sizeof(netmap_iface_context)); if (nic == NULL) { TRACE_ERR("Can't allocate memory for " "netmap_iface_context (for %s)\n", iface); TRACE_NETMAP_FUNC_END(); return -1; } /* resetting base_nmd */ memset(&nic->base_nmd, 0, sizeof(struct nm_desc)); /* resetting fd to -1 */ nic->global_fd = nmc->local_fd = -1; /* use some extra rings */ nic->base_nmd.req.nr_arg3 = NM_EXTRA_BUFS; nic->nmd_flags |= NM_OPEN_ARG3; nic->global_nmd = nm_open((char *)nifname, NULL, nic->nmd_flags, &nic->base_nmd); if (nic->global_nmd == NULL) { TRACE_LOG("Unable to open %s: %s\n", iface, strerror(errno)); free(nic); TRACE_NETMAP_FUNC_END(); return -1; } nic->global_fd = nic->global_nmd->fd; TRACE_DEBUG_LOG("mapped %dKB at %p\n", nic->global_nmd->req.nr_memsize>>10, nic->global_nmd->mem); TRACE_DEBUG_LOG("zerocopy %s", (nic->global_nmd->mem == nic->base_nmd.mem) ? "enabled\n" : "disabled\n"); if (qid != -1) { nic->global_nmd->req.nr_flags = NR_REG_ONE_NIC; nic->global_nmd->req.nr_ringid = qid; } /* create interface entry */ create_interface_entry(iface, (qid == -1) ? NO_QUEUES : HW_QUEUES, IO_NETMAP, nic, nmc->eng); } else { /* otherwise check if that interface can be registered */