diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2011-10-07 16:10:10 +0200 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2011-10-07 16:10:10 +0200 |
commit | 2b4edba3ad8431f8bd8b7218e9f8a5a5e4ee18ac (patch) | |
tree | 6561f793b675ae209e6936d8bf9f25f5749df9d1 | |
parent | f8b192af8b6611c3832df3024cbabaafffb47591 (diff) | |
download | pingu-2b4edba3ad8431f8bd8b7218e9f8a5a5e4ee18ac.tar.bz2 pingu-2b4edba3ad8431f8bd8b7218e9f8a5a5e4ee18ac.tar.xz |
pingu_iface: support binding multiple ping hosts to same iface
Add config option for executing actions when interface gateway goes
up/down.
Add config option for required hosts up per interface (defaults to 1)
-rw-r--r-- | pingu_conf.c | 8 | ||||
-rw-r--r-- | pingu_host.c | 46 | ||||
-rw-r--r-- | pingu_host.h | 3 | ||||
-rw-r--r-- | pingu_iface.c | 36 | ||||
-rw-r--r-- | pingu_iface.h | 9 | ||||
-rw-r--r-- | pingu_netlink.c | 4 |
6 files changed, 78 insertions, 28 deletions
diff --git a/pingu_conf.c b/pingu_conf.c index 30dec9a..ad433e8 100644 --- a/pingu_conf.c +++ b/pingu_conf.c @@ -130,6 +130,14 @@ 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, "label") == 0) { + iface->label = xstrdup(value); + } else if (strcmp(key, "gateway-up-action") == 0) { + iface->gw_up_action = xstrdup(value); + } else if (strcmp(key, "gateway-down-action") == 0) { + iface->gw_down_action = xstrdup(value); + } else if (strcmp(key, "required-hosts-online") == 0) { + iface->required_hosts_online = atoi(value); } else if (strcmp(key, "load-balance") == 0) { int weight = 0; if (value != NULL) { diff --git a/pingu_host.c b/pingu_host.c index a86007f..ca09788 100644 --- a/pingu_host.c +++ b/pingu_host.c @@ -18,10 +18,15 @@ static struct list_head host_list = LIST_INITIALIZER(host_list); -static void execute_action(const char *action) +void execute_action(const char *action) { pid_t pid; - const char *shell = getenv("SHELL"); + const char *shell; + + if (action == NULL) + return; + + shell = getenv("SHELL"); if (shell == NULL) shell = "/bin/sh"; @@ -41,7 +46,7 @@ static void execute_action(const char *action) int pingu_host_set_status(struct pingu_host *host, int status) { const char *action; - int route_action = 0; + int adjustment; host->burst.active = 0; if (host->status == status) { log_debug("%s: status is still %i", host->label, status); @@ -50,18 +55,18 @@ int pingu_host_set_status(struct pingu_host *host, int status) host->status = status; log_info("%s: new status: %i", host->label, status); switch (host->status) { - case 0: + case PINGU_HOST_STATUS_OFFLINE: action = host->down_action; - route_action = RTM_DELROUTE; + adjustment = -1; break; - case 1: + case PINGU_HOST_STATUS_ONLINE: action = host->up_action; - route_action = RTM_NEWROUTE; + adjustment = 1; break; } - if (action != NULL) - execute_action(action); - pingu_iface_update_routes(host->iface, route_action); + + execute_action(action); + pingu_iface_adjust_hosts_online(host->iface, adjustment); return status; } @@ -78,17 +83,17 @@ int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host) struct pingu_host *pingu_host_new(char *hoststr, float burst_interval, int max_retries, int required_replies, - float timeout, + float timeout, const char *up_action, const char *down_action) { struct pingu_host *host = calloc(1, sizeof(struct pingu_host)); - + if (host == NULL) { log_perror(hoststr); return NULL; } - + host->host = hoststr; host->status = PINGU_HOST_DEFAULT_STATUS; host->burst_interval = burst_interval; @@ -97,20 +102,11 @@ struct pingu_host *pingu_host_new(char *hoststr, float burst_interval, host->timeout = timeout; host->up_action = up_action; host->down_action = down_action; - + list_add(&host->host_list_entry, &host_list); return host; } -struct pingu_host *pingu_host_find_by_iface(struct pingu_iface *iface) -{ - struct pingu_host *host; - list_for_each_entry(host, &host_list, host_list_entry) - if (host->iface == iface) - return host; - return NULL; -} - void pingu_host_dump_status(int fd) { struct pingu_host *host; @@ -131,6 +127,10 @@ int pingu_host_init(struct ev_loop *loop) ev_timer_init(&host->burst_timeout_watcher, pingu_burst_timeout_cb, 0, host->burst_interval); ev_timer_start(loop, &host->burst_timeout_watcher); + + if (host->iface->required_hosts_online == 0) + host->iface->required_hosts_online = 1; + host->iface->hosts_online += PINGU_HOST_DEFAULT_STATUS; } return 0; } diff --git a/pingu_host.h b/pingu_host.h index b5f6e48..a7a879d 100644 --- a/pingu_host.h +++ b/pingu_host.h @@ -28,12 +28,13 @@ struct pingu_host { struct pingu_iface *iface; }; +void execute_action(const char *action); + struct pingu_host *pingu_host_new(char *hoststr, float burst_interval, int max_retries, int required_replies, float timeout, const char *up_action, const char *down_action); -struct pingu_host *pingu_host_find_by_iface(struct pingu_iface *iface); int pingu_host_set_status(struct pingu_host *host, int status); int pingu_host_init(struct ev_loop *loop); int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host); diff --git a/pingu_iface.c b/pingu_iface.c index 5ae0317..820546d 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -145,7 +145,7 @@ void pingu_iface_set_balance(struct pingu_iface *iface, int balance_weight) iface->balance = 1; iface->balance_weight = balance_weight; } - + #if 0 void pingu_route_dump(struct pingu_iface *iface) { @@ -187,6 +187,40 @@ void pingu_iface_update_routes(struct pingu_iface *iface, int action) kernel_route_multipath(RTM_NEWROUTE, &iface_list, RT_TABLE_MAIN); } +int pingu_iface_gw_is_online(struct pingu_iface *iface) +{ + return iface->hosts_online >= iface->required_hosts_online; +} + +/* check if we should bring up/down this ISP */ +void pingu_iface_adjust_hosts_online(struct pingu_iface *iface, int adjustment) +{ + int old_status, new_status, route_action; + char *action, *statusstr; + + old_status = pingu_iface_gw_is_online(iface); + iface->hosts_online += adjustment; + new_status = pingu_iface_gw_is_online(iface); + + if (old_status == new_status) + return; + + if (new_status) { + statusstr = "ONLINE"; + route_action = RTM_NEWROUTE; + action = iface->gw_up_action; + } else { + statusstr = "OFFLINE"; + route_action = RTM_DELROUTE; + action = iface->gw_down_action; + } + + log_info("%s: went %s", iface->label ? iface->label : iface->name, + statusstr); + pingu_iface_update_routes(iface, route_action); + execute_action(action); +} + int pingu_iface_set_route_table(struct pingu_iface *iface, int table) { static int initialized = 0; diff --git a/pingu_iface.h b/pingu_iface.h index 14f8ba5..e6c8b24 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -12,6 +12,12 @@ struct pingu_iface { char name[32]; + char *label; + char *gw_up_action; + char *gw_down_action; + int hosts_online; + int required_hosts_online; + int index; int has_link; int has_address; @@ -39,7 +45,10 @@ int pingu_iface_init(struct ev_loop *loop); void pingu_iface_set_balance(struct pingu_iface *iface, int balance_weight); void pingu_iface_set_addr(struct pingu_iface *iface, int family, void *data, int len); +void pingu_iface_adjust_hosts_online(struct pingu_iface *iface, int adjustment); int pingu_iface_set_route_table(struct pingu_iface *iface, int table); + +int pingu_iface_gw_is_online(struct pingu_iface *iface); void pingu_iface_gw_action(struct pingu_iface *iface, struct pingu_route *gw, int action); void pingu_iface_update_routes(struct pingu_iface *iface, int action); diff --git a/pingu_netlink.c b/pingu_netlink.c index 212e8e9..b5e2dd7 100644 --- a/pingu_netlink.c +++ b/pingu_netlink.c @@ -360,7 +360,6 @@ static int add_nexthops(struct nlmsghdr *nlh, size_t nlh_size, struct rtnexthop *rtnh; struct pingu_iface *iface; struct pingu_route *route; - struct pingu_host *host; int count = 0; memset(buf, 0, sizeof(buf)); @@ -372,9 +371,8 @@ static int add_nexthops(struct nlmsghdr *nlh, size_t nlh_size, route = pingu_route_first_default(&iface->route_list); switch (action_type) { case RTM_NEWROUTE: - host = pingu_host_find_by_iface(iface); if ((!iface->balance) || iface->index == 0 - || (host != NULL && host->status == PINGU_HOST_STATUS_OFFLINE) + || !pingu_iface_gw_is_online(iface) || route == NULL) { iface->has_multipath = 0; continue; |