aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2011-08-16 16:47:15 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2011-08-16 16:59:56 +0200
commita6a0c88823b42e4c789b156106d64002b387d291 (patch)
tree82bda92f338e527d3b5eba25fbebc3a2574bc43b
parent04fefe45f6223381df6fbcb7ee7cb72742552fd7 (diff)
downloadpingu-a6a0c88823b42e4c789b156106d64002b387d291.tar.bz2
pingu-a6a0c88823b42e4c789b156106d64002b387d291.tar.xz
pingu: add config option 'load-balance'
Add a config option to tell pingu that we want the interface to be load balanced. We also have an optional value to tell the weight.
-rw-r--r--pingu_conf.c11
-rw-r--r--pingu_iface.h2
-rw-r--r--pingu_netlink.c16
3 files changed, 25 insertions, 4 deletions
diff --git a/pingu_conf.c b/pingu_conf.c
index e9e3b60..9a63aaf 100644
--- a/pingu_conf.c
+++ b/pingu_conf.c
@@ -130,6 +130,17 @@ static int pingu_conf_read_iface(struct pingu_conf *conf, char *ifname)
break;
if (strcmp(key, "route-table") == 0) {
pingu_iface_set_route_table(iface, atoi(value));
+ } else if (strcmp(key, "load-balance") == 0) {
+ iface->balance = 1;
+ if (value != NULL) {
+ iface->balance_weight = atoi(value);
+ if (iface->balance_weight <= 0 || iface->balance_weight > 256) {
+ log_error("Invalid load-balance weight %i on line %i",
+ iface->balance_weight,
+ conf->lineno);
+ return -1;
+ }
+ }
} else {
log_error("Unknown keyword '%s' on line %i", key,
conf->lineno);
diff --git a/pingu_iface.h b/pingu_iface.h
index 4ef67d4..796d17a 100644
--- a/pingu_iface.h
+++ b/pingu_iface.h
@@ -15,6 +15,8 @@ struct pingu_iface {
int index;
int has_binding;
int has_link;
+ int balance;
+ int balance_weight;
int fd;
union sockaddr_any primary_addr;
int route_table;
diff --git a/pingu_netlink.c b/pingu_netlink.c
index aad2a98..2109cc4 100644
--- a/pingu_netlink.c
+++ b/pingu_netlink.c
@@ -294,6 +294,8 @@ static int add_one_nh(struct rtattr *rta, struct rtnexthop *rtnh,
netlink_add_subrtattr_addr_any(rta, 1024, RTA_GATEWAY,
&route->gw_addr);
rtnh->rtnh_len += sizeof(struct rtattr) + 4; // TODO: support ipv6
+ if (iface->balance_weight)
+ rtnh->rtnh_hops = iface->balance_weight - 1;
rtnh->rtnh_ifindex = iface->index;
return 1;
}
@@ -313,7 +315,7 @@ static int add_nexthops(struct nlmsghdr *nlh, size_t nlh_size,
rtnh = RTA_DATA(rta);
list_for_each_entry(iface, iface_list, iface_list_entry) {
- if (iface->index == 0 || list_empty(&iface->gateway_list))
+ if ((!iface->balance) || iface->index == 0 || list_empty(&iface->gateway_list))
continue;
memset(rtnh, 0, sizeof(*rtnh));
rtnh->rtnh_len = sizeof(*rtnh);
@@ -337,6 +339,7 @@ int netlink_route_multipath(struct netlink_fd *fd, int action_type,
} req;
struct sockaddr_nl addr;
union sockaddr_any dest;
+ int count = 0;
memset(&req, 0, sizeof(req));
memset(&addr, 0, sizeof(addr));
@@ -355,16 +358,21 @@ int netlink_route_multipath(struct netlink_fd *fd, int action_type,
req.msg.rtm_family = AF_INET;
req.msg.rtm_table = table;
req.msg.rtm_dst_len = 0;
- req.msg.rtm_protocol = RTPROT_UNSPEC;
+ req.msg.rtm_protocol = RTPROT_BOOT;
req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
req.msg.rtm_type = RTN_UNICAST;
netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), RTA_DST,
&dest);
- add_nexthops(&req.nlh, sizeof(req), iface_list);
- return sendto(fd->fd, (void *) &req, sizeof(req), 0,
+ count = add_nexthops(&req.nlh, sizeof(req), iface_list);
+ if (count > 1) {
+ return sendto(fd->fd, (void *) &req, sizeof(req), 0,
(struct sockaddr *) &addr, sizeof(addr));
+ }
+ if (count == 1)
+ log_debug("Not load-balancing a single gateway");
+ return 0;
}
int netlink_route_replace_or_add(struct netlink_fd *fd,