-
Notifications
You must be signed in to change notification settings - Fork 136
JSON load balancer config file #328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
c11085f
3fcccd1
26a559b
5bb21ab
f64193a
82a2749
647d844
2d1aff8
2ea6147
7766664
a7c96bc
162c5bc
28afd8a
5ae3696
e75a096
756240b
92158a5
23efebe
e0d56f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,10 +69,14 @@ | |
#include "onvm_flow_table.h" | ||
#include "onvm_nflib.h" | ||
#include "onvm_pkt_helper.h" | ||
#include "onvm_config_common.h" | ||
#include "cJSON.h" | ||
|
||
#define NF_TAG "load_balancer" | ||
#define TABLE_SIZE 65536 | ||
|
||
enum lb_policy {RROBIN, RANDOM, WEIGHTED_RANDOM}; | ||
|
||
/* Struct for load balancer information */ | ||
struct loadbalance { | ||
struct onvm_ft *ft; | ||
|
@@ -95,6 +99,14 @@ struct loadbalance { | |
|
||
/* config file */ | ||
char *cfg_filename; | ||
|
||
/* LB policy */ | ||
// char *policy; | ||
enum lb_policy policy; | ||
|
||
/* structures to store server weights */ | ||
int *weights; | ||
int total_weight; | ||
}; | ||
|
||
/* Struct for backend servers */ | ||
|
@@ -115,6 +127,9 @@ struct loadbalance *lb; | |
/* number of package between each print */ | ||
static uint32_t print_delay = 1000000; | ||
|
||
/* switch for turning on debug mode */ | ||
static int debug_mode = 0; | ||
|
||
/* onvm struct for port info lookup */ | ||
extern struct port_info *ports; | ||
|
||
|
@@ -136,6 +151,7 @@ usage(const char *progname) { | |
printf(" - `-t SERVER_PORT` : server port ID\n"); | ||
printf(" - `-f SERVER_CONFIG` : backend server config file\n"); | ||
printf(" - `-p <print_delay>`: number of packets between each print, e.g. `-p 1` prints every packets.\n"); | ||
printf(" - `-d`: debug info including when connections are recieved and when packets are recieved.\n"); | ||
} | ||
|
||
/* | ||
|
@@ -164,7 +180,7 @@ parse_app_args(int argc, char *argv[], const char *progname) { | |
lb->client_port = RTE_MAX_ETHPORTS; | ||
lb->server_port = RTE_MAX_ETHPORTS; | ||
|
||
while ((c = getopt(argc, argv, "c:r:s:t:f:p:")) != -1) { | ||
while ((c = getopt(argc, argv, "c:r:s:t:f:p:d")) != -1) { | ||
switch (c) { | ||
case 'c': | ||
ret = parse_iface_ip(strdup(optarg), &lb->ip_lb_client); | ||
|
@@ -192,11 +208,12 @@ parse_app_args(int argc, char *argv[], const char *progname) { | |
case 'p': | ||
print_delay = strtoul(optarg, NULL, 10); | ||
break; | ||
case 'd': | ||
debug_mode = 1; | ||
break; | ||
case '?': | ||
usage(progname); | ||
if (optopt == 'd') | ||
RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); | ||
else if (optopt == 'p') | ||
if (optopt == 'p') | ||
RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); | ||
else if (isprint(optopt)) | ||
RTE_LOG(INFO, APP, "Unknown option `-%c'.\n", optopt); | ||
|
@@ -240,49 +257,81 @@ parse_app_args(int argc, char *argv[], const char *progname) { | |
/* | ||
* This function parses the backend config. It takes the filename | ||
* and fills up the backend_server array. This includes the mac and ip | ||
* address of the backend servers | ||
* address of the backend servers as well as their weights | ||
*/ | ||
static int | ||
parse_backend_config(void) { | ||
int ret, temp, i; | ||
char ip[32]; | ||
char mac[32]; | ||
FILE *cfg; | ||
parse_backend_json_config(void) { | ||
int ret, i; | ||
i = 0; | ||
|
||
cfg = fopen(lb->cfg_filename, "r"); | ||
if (cfg == NULL) { | ||
rte_exit(EXIT_FAILURE, "Error openning server \'%s\' config\n", lb->cfg_filename); | ||
} | ||
ret = fscanf(cfg, "%*s %d", &temp); | ||
if (temp <= 0) { | ||
rte_exit(EXIT_FAILURE, "Error parsing config, need at least one server configurations\n"); | ||
cJSON *config_json = onvm_config_parse_file(lb->cfg_filename); | ||
cJSON *list_size = NULL; | ||
cJSON *policy = NULL; | ||
cJSON *ip_addr = NULL; | ||
cJSON *mac_addr = NULL; | ||
cJSON *weight = NULL; | ||
|
||
if (config_json == NULL) { | ||
rte_exit(EXIT_FAILURE, "%s file could not be parsed or was not found. Assure" | ||
" the directory to the config file is being specified.\n", lb->cfg_filename); | ||
andreaseno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
lb->server_count = temp; | ||
|
||
config_json = config_json -> child; | ||
|
||
list_size = cJSON_GetObjectItem(config_json, "list_size"); | ||
policy = cJSON_GetObjectItem(config_json, "policy"); | ||
|
||
if (list_size == NULL) rte_exit(EXIT_FAILURE, "list_size not found/invalid\n"); | ||
if (policy == NULL) rte_exit(EXIT_FAILURE, "policy not found/invalid\n"); | ||
|
||
|
||
lb->server_count = list_size->valueint; | ||
|
||
if (!strcmp(policy->valuestring, "RROBIN")) lb->policy = RROBIN; | ||
else if (!strcmp(policy->valuestring, "RANDOM")) lb->policy = RANDOM; | ||
else if (!strcmp(policy->valuestring, "WEIGHTED_RANDOM")) lb->policy = WEIGHTED_RANDOM; | ||
else rte_exit(EXIT_FAILURE, "Invalid policy. Check server.json\n"); | ||
|
||
lb->weights = (int*)calloc(lb->server_count,sizeof(int)); | ||
andreaseno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
lb->server = (struct backend_server *)rte_malloc("backend server info", | ||
sizeof(struct backend_server) * lb->server_count, 0); | ||
if (lb->server == NULL) { | ||
rte_exit(EXIT_FAILURE, "Malloc failed, can't allocate server information\n"); | ||
} | ||
|
||
for (i = 0; i < lb->server_count; i++) { | ||
ret = fscanf(cfg, "%s %s", ip, mac); | ||
if (ret != 2) { | ||
rte_exit(EXIT_FAILURE, "Invalid backend config structure\n"); | ||
} | ||
config_json = config_json->next; | ||
|
||
while (config_json != NULL) { | ||
andreaseno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ip_addr = cJSON_GetObjectItem(config_json, "ip"); | ||
mac_addr = cJSON_GetObjectItem(config_json, "mac_addr"); | ||
weight = cJSON_GetObjectItem(config_json, "weight"); | ||
|
||
ret = onvm_pkt_parse_ip(ip, &lb->server[i].d_ip); | ||
if (ip_addr == NULL) rte_exit(EXIT_FAILURE, "IP not found/invalid\n"); | ||
if (mac_addr == NULL) rte_exit(EXIT_FAILURE, "MAC address not found/invalid\n"); | ||
|
||
|
||
ret = onvm_pkt_parse_ip(ip_addr->valuestring, &lb->server[i].d_ip); | ||
if (ret < 0) { | ||
rte_exit(EXIT_FAILURE, "Error parsing config IP address #%d\n", i); | ||
} | ||
|
||
ret = onvm_pkt_parse_mac(mac, lb->server[i].d_addr_bytes); | ||
ret = onvm_pkt_parse_mac(mac_addr->valuestring, lb->server[i].d_addr_bytes); | ||
if (ret < 0) { | ||
rte_exit(EXIT_FAILURE, "Error parsing config MAC address #%d\n", i); | ||
} | ||
|
||
if (lb->policy != WEIGHTED_RANDOM) lb->weights[i] = 1; | ||
else { | ||
if (weight == NULL) rte_exit(EXIT_FAILURE, "Weight not found/invalid\n"); | ||
lb->weights[i] = weight->valueint; | ||
lb->total_weight += weight->valueint; | ||
} | ||
config_json = config_json->next; | ||
i++; | ||
} | ||
if ( i != lb->server_count) rte_exit(EXIT_FAILURE, "Invalid list_size in config file\n"); | ||
cJSON_Delete(config_json); | ||
|
||
fclose(cfg); | ||
printf("\nARP config:\n"); | ||
for (i = 0; i < lb->server_count; i++) { | ||
printf("%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 " ", (lb->server[i].d_ip >> 24) & 0xFF, | ||
|
@@ -460,10 +509,34 @@ table_add_entry(struct onvm_ft_ipv4_5tuple *key, struct flow_info **flow) { | |
} | ||
|
||
lb->num_stored++; | ||
data->dest = lb->num_stored % lb->server_count; | ||
|
||
int i, wrand, cur_weight_sum; | ||
switch (lb->policy) | ||
{ | ||
case RANDOM: | ||
data->dest = rand() % lb->server_count; | ||
break; | ||
case RROBIN: | ||
data->dest = lb->num_stored % lb->server_count; | ||
break; | ||
case WEIGHTED_RANDOM: | ||
wrand = rand() % lb->total_weight; | ||
cur_weight_sum=0; | ||
for (i = 0; i < lb->server_count; i++) { | ||
cur_weight_sum+=lb->weights[i]; | ||
if(wrand < cur_weight_sum) { | ||
data->dest=i; | ||
break; | ||
} | ||
} | ||
break; | ||
default: | ||
rte_exit(EXIT_FAILURE, "Invalid policy while adding entry to table!\n"); | ||
break; | ||
} | ||
|
||
data->last_pkt_cycles = lb->elapsed_cycles; | ||
data->is_active = 0; | ||
|
||
*flow = data; | ||
|
||
return 0; | ||
|
@@ -518,10 +591,12 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, | |
struct rte_ipv4_hdr *ip; | ||
struct rte_ether_hdr *ehdr; | ||
struct flow_info *flow_info; | ||
struct rte_tcp_hdr* tcp; | ||
int i, ret; | ||
|
||
ehdr = onvm_pkt_ether_hdr(pkt); | ||
ip = onvm_pkt_ipv4_hdr(pkt); | ||
tcp = onvm_pkt_tcp_hdr(pkt); | ||
|
||
/* Ignore packets without ip header, also ignore packets with invalid ip */ | ||
if (ip == NULL || ip->src_addr == 0 || ip->dst_addr == 0) { | ||
|
@@ -555,6 +630,12 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, | |
for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { | ||
flow_info->s_addr_bytes[i] = ehdr->s_addr.addr_bytes[i]; | ||
} | ||
if(debug_mode) { | ||
printf("New connection made with server %d.\n",flow_info->dest); | ||
printf("Source IP: %" PRIu32 " (%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 ":%" PRIu16") made a new connection with server %d.\n", ip->src_addr, | ||
ip->src_addr & 0xFF, (ip->src_addr >> 8) & 0xFF, (ip->src_addr >> 16) & 0xFF, | ||
(ip->src_addr >> 24) & 0xFF, rte_be_to_cpu_16(tcp->src_port),flow_info->dest); | ||
} | ||
} | ||
|
||
if (pkt->port == lb->server_port) { | ||
|
@@ -600,6 +681,10 @@ main(int argc, char *argv[]) { | |
int arg_offset; | ||
const char *progname = argv[0]; | ||
|
||
time_t t; | ||
/* Intializes RANDOM number generator */ | ||
srand((unsigned) time(&t)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check indentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the issue with the indentation here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like tabs not spaces. @catherinemeadows -- do you know if we have a working linter script that checks for this kind of formatting issue in ONVM? I thought our GitHub actions would do it automatically, but it seems not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, in |
||
|
||
nf_local_ctx = onvm_nflib_init_nf_local_ctx(); | ||
onvm_nflib_start_signal_handler(nf_local_ctx, NULL); | ||
|
||
|
@@ -636,14 +721,16 @@ main(int argc, char *argv[]) { | |
} | ||
|
||
validate_iface_config(); | ||
parse_backend_config(); | ||
parse_backend_json_config(); | ||
|
||
lb->expire_time = 32; | ||
lb->elapsed_cycles = rte_get_tsc_cycles(); | ||
|
||
onvm_nflib_run(nf_local_ctx); | ||
|
||
onvm_nflib_stop(nf_local_ctx); | ||
|
||
free(lb->weights); | ||
onvm_ft_free(lb->ft); | ||
rte_free(lb); | ||
printf("If we reach here, program is ending\n"); | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"Info" : { | ||
"list_size": 2, | ||
"policy": "RANDOM" | ||
}, | ||
|
||
"Server0": { | ||
"ip": "10.10.1.2", | ||
"mac_addr": "90:e2:ba:ac:16:34", | ||
"weight": 1 | ||
}, | ||
|
||
"Server1": { | ||
"ip": "10.10.1.3", | ||
"mac_addr": "90:e2:ba:b3:bb:7d", | ||
"weight": 1 | ||
} | ||
} | ||
andreaseno marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.