summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Larson <slioch@eng-140.vyatta.com>2008-06-30 17:06:19 -0700
committerMichael Larson <slioch@eng-140.vyatta.com>2008-06-30 17:06:19 -0700
commitb49594b52dd12caa72b868792e949647377361db (patch)
tree81d5ca98442195e78d41e955a9cfef8326a4168d
parentf5f5de597b8d488b911f3c74b173115403e40991 (diff)
downloadvyatta-wanloadbalance-b49594b52dd12caa72b868792e949647377361db.tar.gz
vyatta-wanloadbalance-b49594b52dd12caa72b868792e949647377361db.zip
fix for bug 3393. apply default route on poll interval if route is not present in policy table. This fixes a problem if the interface is
not ready to receive the route on initial insertion.
-rw-r--r--src/lbdecision.cc143
-rw-r--r--src/lbdecision.hh9
2 files changed, 100 insertions, 52 deletions
diff --git a/src/lbdecision.cc b/src/lbdecision.cc
index 1c2591f..56ada69 100644
--- a/src/lbdecision.cc
+++ b/src/lbdecision.cc
@@ -106,18 +106,19 @@ if so then this stuff goes here!
//note: doesn't appear to clean up rule table, may need to individually erase each rule
// execute(string("ip rule flush"));
+ string stdout;
//set up special nat rules
- execute(string("iptables -t nat -N WANLOADBALANCE"));
- execute(string("iptables -t nat -F WANLOADBALANCE"));
- execute(string("iptables -t nat -D POSTROUTING -j WANLOADBALANCE"));
- execute(string("iptables -t nat -A POSTROUTING -j WANLOADBALANCE"));
+ execute(string("iptables -t nat -N WANLOADBALANCE"), stdout);
+ execute(string("iptables -t nat -F WANLOADBALANCE"), stdout);
+ execute(string("iptables -t nat -D POSTROUTING -j WANLOADBALANCE"), stdout);
+ execute(string("iptables -t nat -A POSTROUTING -j WANLOADBALANCE"), stdout);
//set up the conntrack table
- execute(string("iptables -t raw -N NAT_CONNTRACK"));
- execute(string("iptables -t raw -F NAT_CONNTRACK"));
- execute(string("iptables -t raw -A NAT_CONNTRACK -j ACCEPT"));
- execute(string("iptables -t raw -D PREROUTING 1"));
- execute(string("iptables -t raw -I PREROUTING 1 -j NAT_CONNTRACK"));
+ execute(string("iptables -t raw -N NAT_CONNTRACK"), stdout);
+ execute(string("iptables -t raw -F NAT_CONNTRACK"), stdout);
+ execute(string("iptables -t raw -A NAT_CONNTRACK -j ACCEPT"), stdout);
+ execute(string("iptables -t raw -D PREROUTING 1"), stdout);
+ execute(string("iptables -t raw -I PREROUTING 1 -j NAT_CONNTRACK"), stdout);
LBData::InterfaceHealthIter iter = lbdata._iface_health_coll.begin();
@@ -126,28 +127,28 @@ if so then this stuff goes here!
sprintf(buf,"%d",ct);
- execute(string("iptables -t mangle -N ISP_") + buf);
- execute(string("iptables -t mangle -F ISP_") + buf);
- execute(string("iptables -t mangle -A ISP_") + buf + " -j CONNMARK --set-mark " + buf);
+ execute(string("iptables -t mangle -N ISP_") + buf, stdout);
+ execute(string("iptables -t mangle -F ISP_") + buf, stdout);
+ execute(string("iptables -t mangle -A ISP_") + buf + " -j CONNMARK --set-mark " + buf, stdout);
//NOTE, WILL NEED A WAY TO CLEAN UP THIS RULE ON RESTART...
- execute(string("iptables -t mangle -A ISP_") + buf + " -j ACCEPT");
+ execute(string("iptables -t mangle -A ISP_") + buf + " -j ACCEPT", stdout);
- execute(string("ip route replace table ") + buf + " default dev " + iface + " via " + iter->second._nexthop);
- execute(string("ip rule delete table ") + buf);
+ insert_default(string("ip route replace table ") + buf + " default dev " + iface + " via " + iter->second._nexthop, ct);
+ _iface_mark_coll.insert(pair<string,int>(iface,ct));
+
+ execute(string("ip rule delete table ") + buf, stdout);
char hex_buf[40];
sprintf(hex_buf,"%X",ct);
- execute(string("ip rule add fwmark ") + hex_buf + " table " + buf);
+ execute(string("ip rule add fwmark ") + hex_buf + " table " + buf, stdout);
- execute(string("iptables -t nat -A WANLOADBALANCE -m connmark --mark ") + buf + " -j SNAT --to-source " + fetch_iface_addr(iface));
+ execute(string("iptables -t nat -A WANLOADBALANCE -m connmark --mark ") + buf + " -j SNAT --to-source " + fetch_iface_addr(iface), stdout);
- string tmp = string("table ") + buf + " default dev " + iface + " via " + iter->second._nexthop;
- _iface_mark_coll.insert(pair<string,string>(iface,tmp));
++ct;
++iter;
}
- execute("ip route flush cache");
+ execute("ip route flush cache", stdout);
}
@@ -168,10 +169,7 @@ LBDecision::run(LBData &lb_data)
cout << "LBDecision::run(), starting decision" << endl;
}
- //first determine if we need to alter the rule set
- if (!lb_data.state_changed()) {
- return;
- }
+ string stdout;
if (_debug) {
cout << "LBDecision::run(), state changed, applying new rule set" << endl;
@@ -186,7 +184,9 @@ LBDecision::run(LBData &lb_data)
route_str = m_iter->second;
if (h_iter->second._is_active == true) {
- execute(string("ip route replace ") + route_str);
+ char buf[40];
+ sprintf(buf,"%d",m_iter->second);
+ insert_default(string("ip route replace table ") + buf + " default dev " + h_iter->first + " via " + h_iter->second._nexthop, m_iter->second);
}
else {
//right now replace route, but don't delete until race condition is resolved
@@ -197,8 +197,13 @@ LBDecision::run(LBData &lb_data)
++h_iter;
}
+ //first determine if we need to alter the rule set
+ if (!lb_data.state_changed()) {
+ return;
+ }
+
//then if we do, flush all
- execute("iptables -t mangle -F PREROUTING");
+ execute("iptables -t mangle -F PREROUTING", stdout);
//and compute the new set and apply
LBData::LBRuleIter iter = lb_data._lb_rule_coll.begin();
@@ -214,8 +219,8 @@ LBDecision::run(LBData &lb_data)
}
else if (weights.size() == 1) {
sprintf(dbuf,"%d",w_iter->first);
- execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -j ISP_" + dbuf);
- execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -j CONNMARK --restore-mark");
+ execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -j ISP_" + dbuf, stdout);
+ execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -j CONNMARK --restore-mark", stdout);
}
else {
map<int,float>::iterator w_end = weights.end();
@@ -223,14 +228,14 @@ LBDecision::run(LBData &lb_data)
while (w_iter != w_end) {
sprintf(fbuf,"%f",w_iter->second);
sprintf(dbuf,"%d",w_iter->first);
- execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -m statistic --mode random --probability " + fbuf + " -j ISP_" + dbuf);
+ execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -m statistic --mode random --probability " + fbuf + " -j ISP_" + dbuf, stdout);
++w_iter;
}
//last one is special case, the catch all rule
++w_iter;
sprintf(dbuf,"%d",w_iter->first);
- execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -j ISP_" + dbuf);
- execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -j CONNMARK --restore-mark");
+ execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -m state --state NEW -j ISP_" + dbuf, stdout);
+ execute(string("iptables -t mangle -A PREROUTING ") + app_cmd + " -j CONNMARK --restore-mark", stdout);
}
++iter;
continue;
@@ -244,14 +249,18 @@ LBDecision::run(LBData &lb_data)
void
LBDecision::shutdown()
{
+ string stdout;
+
//then if we do, flush all
- execute("iptables -t mangle -F PREROUTING");
+ execute("iptables -t mangle -F PREROUTING", stdout);
//remove the policy entries
InterfaceMarkIter iter = _iface_mark_coll.begin();
while (iter != _iface_mark_coll.end()) {
-
- execute(string("ip rule del table ") + iter->second);
+ char buf[40];
+ sprintf(buf,"%d",iter->second);
+
+ execute(string("ip rule del table ") + buf, stdout);
//need to delete ip rule here as well!
@@ -261,33 +270,44 @@ LBDecision::shutdown()
/**
*
- *
**/
-void
-LBDecision::execute(string cmd)
+int
+LBDecision::execute(std::string cmd, std::string &stdout, bool read)
{
+ int err = 0;
+
if (_debug) {
cout << "LBDecision::execute(): applying command to system: " << cmd << endl;
syslog(LOG_DEBUG, "LBDecision::execute(): applying command to system: %s",cmd.c_str());
}
- FILE *f = popen(cmd.c_str(), "w");
+ string dir = "w";
+ if (read == true) {
+ dir = "r";
+ }
+ FILE *f = popen(cmd.c_str(), dir.c_str());
if (f) {
- if (pclose(f) != 0) {
- if (_debug) {
- cerr << "LBDecision::execute(): error executing command: " << cmd << endl;
+ if (read == true) {
+ fflush(f);
+ char *buf = NULL;
+ size_t len = 0;
+ size_t read_len = 0;
+ while ((read_len = getline(&buf, &len, f)) != -1) {
+ stdout += string(buf) + " ";
+ }
+
+ if (buf) {
+ free(buf);
}
- syslog(LOG_ERR, "Error executing system command: %s", cmd.c_str());
- }
- }
- else {
- if (_debug) {
- cerr << "LBDecision::execute(): error executing command: " << cmd << endl;
}
- syslog(LOG_ERR, "Error executing system command: %s", cmd.c_str());
+ err = pclose(f);
}
+ return err;
}
+/**
+ *
+ **/
map<int,float>
LBDecision::get_new_weights(LBData &data, LBRule &rule)
{
@@ -414,7 +434,32 @@ LBDecision::get_application_cmd(LBRule &rule)
}
-/* Fetch interface configuration */
+/**
+ * Check for the presence of a route entry in the policy table. Note this
+ * should be replaced by netlink in the next release.
+ **/
+void
+LBDecision::insert_default(string cmd, int table)
+{
+ string stdout;
+ char buf[40];
+ string showcmd("ip route show table ");
+ sprintf(buf,"%d",table);
+ showcmd += string(buf);
+ execute(showcmd,stdout,true);
+
+ // cout << "LBDecision::insert_default(stdout): '" << stdout << "'" << endl;
+
+ if (stdout.empty() == true) {
+ // cout << "LBDecision::insert_default(cmd): " << cmd << endl;
+ execute(cmd,stdout);
+ }
+}
+
+
+/**
+ * Fetch interface configuration
+ **/
string
LBDecision::fetch_iface_addr(const string &iface)
{
diff --git a/src/lbdecision.hh b/src/lbdecision.hh
index f736f93..76869fa 100644
--- a/src/lbdecision.hh
+++ b/src/lbdecision.hh
@@ -17,8 +17,8 @@ using namespace std;
class LBDecision
{
public:
- typedef map<string,string> InterfaceMarkColl;
- typedef map<string,string>::iterator InterfaceMarkIter;
+ typedef map<string,int> InterfaceMarkColl;
+ typedef map<string,int>::iterator InterfaceMarkIter;
public:
LBDecision(bool debug);
@@ -34,8 +34,11 @@ public:
shutdown();
private:
+ int
+ execute(string cmd, string &stdout, bool read = false);
+
void
- execute(string cmd);
+ insert_default(string cmd, int table);
map<int,float>
get_new_weights(LBData &data, LBRule &rule);