static int lua_to_stream_cfg(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct stream_cfg **stream_cfg, struct hash_set *hs) { int pop; struct stream_cfg *ret; if ((pop = lua_getfrom(L, from, name)) < 0) return -1; if (lua_getfrom(L, TABLE, "actions") < 0) return -1; lua_len(prox_lua(), -1); uint32_t n_actions = lua_tointeger(prox_lua(), -1); lua_pop(prox_lua(), 1); lua_pop(L, 1); size_t mem_size = 0; mem_size += sizeof(*ret); /* one additional action is allocated to allow inserting an additional "default" action to close down TCP sessions from the client side. */ mem_size += sizeof(ret->actions[0]) * (n_actions + 1); ret = prox_zmalloc(sizeof(*ret) + mem_size, socket); ret->n_actions = n_actions; size_t client_contents_len, server_contents_len; char proto[16]; uint32_t timeout_us, timeout_time_wait_us; plogx_dbg("loading stream\n"); if (lua_to_host_set(L, TABLE, "servers", &ret->servers)) return -1; if (lua_to_string(L, TABLE, "l4_proto", proto, sizeof(proto))) return -1; if (lua_to_peer_data(L, TABLE, "client_data", socket, &ret->data[PEER_CLIENT], &client_contents_len, hs)) return -1; if (lua_to_peer_data(L, TABLE, "server_data", socket, &ret->data[PEER_SERVER], &server_contents_len, hs)) return -1; if (lua_to_int(L, TABLE, "timeout", &timeout_us)) { timeout_us = 1000000; } ret->tsc_timeout = usec_to_tsc(timeout_us); double up, dn; if (lua_to_double(L, TABLE, "up_bps", &up)) up = 5000;// Default rate is 40 Mbps if (lua_to_double(L, TABLE, "dn_bps", &dn)) dn = 5000;// Default rate is 40 Mbps const uint64_t hz = rte_get_tsc_hz(); ret->tt_cfg[PEER_CLIENT] = token_time_cfg_create(up, hz, ETHER_MAX_LEN + 20); ret->tt_cfg[PEER_SERVER] = token_time_cfg_create(dn, hz, ETHER_MAX_LEN + 20); if (!strcmp(proto, "tcp")) { ret->proto = IPPROTO_TCP; ret->proc = stream_tcp_proc; ret->is_ended = stream_tcp_is_ended; if (lua_to_int(L, TABLE, "timeout_time_wait", &timeout_time_wait_us)) { timeout_time_wait_us = 2000000; } ret->tsc_timeout_time_wait = usec_to_tsc(timeout_time_wait_us); } else if (!strcmp(proto, "udp")) { plogx_dbg("loading UDP\n"); ret->proto = IPPROTO_UDP; ret->proc = stream_udp_proc; ret->is_ended = stream_udp_is_ended; } else return -1; /* get all actions */ if (lua_getfrom(L, TABLE, "actions") < 0) return -1; uint32_t idx = 0; lua_pushnil(L); while (lua_next(L, -2)) { if (lua_to_peer_action(L, STACK, NULL, &ret->actions[idx], client_contents_len, server_contents_len)) return -1; stream_cfg_verify_action(ret, &ret->actions[idx]); idx++; lua_pop(L, 1); } lua_pop(L, 1); /* For TCP, one of the peers initiates closing down the connection. This is signified by the last action having with zero length. If such an action is not specified in the configuration file, the default is for the client to close the connection. This means that the TCP connection at the client will go into a TIME_WAIT state and the server releases all the resources avoiding resource starvation at the server. */ if (ret->proto == IPPROTO_TCP && ret->actions[ret->n_actions - 1].len != 0) { ret->actions[ret->n_actions].len = 0; ret->actions[ret->n_actions].beg = 0; ret->actions[ret->n_actions].peer = PEER_CLIENT; ret->n_actions++; } if (IPPROTO_TCP == ret->proto) stream_tcp_calc_len(ret, &ret->n_pkts, &ret->n_bytes); else stream_udp_calc_len(ret, &ret->n_pkts, &ret->n_bytes); lua_pop(L, pop); *stream_cfg = ret; return 0; }
static int lua_to_stream_cfg(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct stream_cfg **stream_cfg) { int pop; struct stream_cfg *ret; if ((pop = lua_getfrom(L, from, name)) < 0) return -1; if (lua_getfrom(L, TABLE, "actions") < 0) return -1; lua_len(prox_lua(), -1); uint32_t n_actions = lua_tointeger(prox_lua(), -1); lua_pop(prox_lua(), 1); lua_pop(L, 1); size_t mem_size = 0; mem_size += sizeof(*ret); mem_size += sizeof(ret->actions[0])*n_actions; ret = rte_zmalloc_socket(NULL, sizeof(*ret) + mem_size, RTE_CACHE_LINE_SIZE, socket); ret->n_actions = n_actions; size_t client_contents_len, server_contents_len; char proto[16]; uint32_t timeout_us, timeout_time_wait_us; plogx_dbg("loading stream\n"); if (lua_to_host_set(L, TABLE, "servers", &ret->servers) || lua_to_string(L, TABLE, "l4_proto", proto, sizeof(proto)) || lua_to_peer_data(L, TABLE, "client_data", socket, &ret->data[PEER_CLIENT], &client_contents_len) || lua_to_peer_data(L, TABLE, "server_data", socket, &ret->data[PEER_SERVER], &server_contents_len)) { return -1; } if (lua_to_int(L, TABLE, "timeout", &timeout_us)) { timeout_us = 1000000; } ret->tsc_timeout = (uint64_t)timeout_us * rte_get_tsc_hz()/1000000; if (!strcmp(proto, "tcp")) { ret->proto = IPPROTO_TCP; ret->proc = stream_tcp_proc; ret->is_ended = stream_tcp_is_ended; if (lua_to_int(L, TABLE, "timeout_time_wait", &timeout_time_wait_us)) { timeout_time_wait_us = 2000000; } ret->tsc_timeout_time_wait = (uint64_t)timeout_time_wait_us * rte_get_tsc_hz()/1000000; } else if (!strcmp(proto, "udp")) { plogx_dbg("loading UDP\n"); ret->proto = IPPROTO_UDP; ret->proc = stream_udp_proc; ret->is_ended = stream_udp_is_ended; } else return -1; /* get all actions */ if (lua_getfrom(L, TABLE, "actions") < 0) return -1; uint32_t idx = 0; lua_pushnil(L); while (lua_next(L, -2)) { if (lua_to_peer_action(L, STACK, NULL, &ret->actions[idx], client_contents_len, server_contents_len)) return -1; idx++; lua_pop(L, 1); } lua_pop(L, 1); lua_pop(L, pop); *stream_cfg = ret; return 0; }