summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorslioch <slioch@eng-140.vyatta.com>2009-07-21 11:50:09 -0700
committerslioch <slioch@eng-140.vyatta.com>2009-07-21 11:50:09 -0700
commitf947ef5883cd890a2cdc3e250f6790f3a630492f (patch)
treeceb0582cfb652bbef942f3a63661a3a60f9adb9a /src
parent25d9851b65fed9297caaa01b47ec6bae76d8c954 (diff)
downloadvyatta-wanloadbalance-f947ef5883cd890a2cdc3e250f6790f3a630492f.tar.gz
vyatta-wanloadbalance-f947ef5883cd890a2cdc3e250f6790f3a630492f.zip
added udp ttl limited test type to health check. modified configuration layout. modified op mode command to
provide indication on multiple target success/failures.
Diffstat (limited to 'src')
-rw-r--r--src/lbdata.cc89
-rw-r--r--src/lbdata.hh17
-rw-r--r--src/lbdatafactory.cc33
-rw-r--r--src/lbdatafactory.hh2
-rw-r--r--src/lboutput.cc10
-rw-r--r--src/lbtest_icmp.cc128
-rw-r--r--src/lbtest_icmp.hh13
7 files changed, 190 insertions, 102 deletions
diff --git a/src/lbdata.cc b/src/lbdata.cc
index 0d06918..9c33f51 100644
--- a/src/lbdata.cc
+++ b/src/lbdata.cc
@@ -6,6 +6,19 @@
* by the Free Software Foundation.
*/
#include <sys/time.h>
+#include <syslog.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/udp.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <errno.h>
+#include <string.h>
#include <time.h>
#include <syslog.h>
#include <iostream>
@@ -15,6 +28,11 @@
int LBHealthHistory::_buffer_size = 10;
+int LBTest::_send_icmp_sock = 0;
+int LBTest::_send_raw_sock = 0;
+int LBTest::_recv_icmp_sock = 0;
+bool LBTest::_initialized = false;
+
/**
*
*
@@ -190,9 +208,9 @@ LBData::dump()
LBHealth::TestIter t_iter = h_iter->second._test_coll.begin();
while (t_iter != h_iter->second._test_coll.end()) {
cout << " test: " << t_iter->first << endl;
- cout << " target: " << t_iter->second->_target << endl;
- cout << " resp time:" << t_iter->second->_resp_time << endl;
- ++t_iter;
+ string foo = t_iter->second->dump();
+ cout << " " << foo << endl;
+ ++t_iter;
}
++h_iter;
}
@@ -297,3 +315,68 @@ LBData::update_dhcp_nexthop()
++h_iter;
}
}
+
+/**
+ *
+ *
+ **/
+void
+LBTest::init()
+{
+ if (_initialized == true) {
+ return;
+ }
+ _initialized = true;
+
+ struct protoent *ppe = getprotobyname("icmp");
+ _send_icmp_sock = socket(PF_INET, SOCK_RAW, ppe->p_proto);
+ if (_send_icmp_sock < 0){
+ if (_debug) {
+ cerr << "LBTestICMP::LBTestICMP(): no send sock: " << _send_icmp_sock << endl;
+ }
+ syslog(LOG_ERR, "wan_lb: failed to acquired socket");
+ _send_icmp_sock = 0;
+ return;
+ }
+
+ //set options for broadcasting.
+ int val = 1;
+ // setsockopt(_send_icmp_sock, SOL_SOCKET, SO_BROADCAST, &val, 4);
+ setsockopt(_send_icmp_sock, SOL_SOCKET, SO_REUSEADDR, &val, 4);
+
+ _send_raw_sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
+ if (_send_raw_sock < 0){
+ if (_debug) {
+ cerr << "LBTestICMP::LBTestICMP(): no send sock: " << _send_raw_sock << endl;
+ }
+ syslog(LOG_ERR, "wan_lb: failed to acquired socket");
+ _send_raw_sock = 0;
+ return;
+ }
+
+ //set options for broadcasting.
+ // setsockopt(_send_raw_sock, SOL_SOCKET, SO_BROADCAST, &val, 4);
+ setsockopt(_send_raw_sock, SOL_SOCKET, SO_REUSEADDR, &val, 4);
+
+ struct sockaddr_in addr;
+ memset( &addr, 0, sizeof( struct sockaddr_in ));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+
+ _recv_icmp_sock = socket(PF_INET, SOCK_RAW, ppe->p_proto);
+ if (_recv_icmp_sock < 0) {
+ if (_debug) {
+ cerr << "LBTestICMP::LBTestICMP(): no recv sock: " << _recv_icmp_sock << endl;
+ }
+ syslog(LOG_ERR, "wan_lb: failed to acquired socket");
+ _recv_icmp_sock = 0;
+ return;
+ }
+ if (bind(_recv_icmp_sock, (struct sockaddr*)&addr, sizeof(addr))==-1) {
+ if (_debug) {
+ cerr << "failed on bind" << endl;
+ }
+ syslog(LOG_ERR, "wan_lb: failed to bind recv sock");
+ }
+}
diff --git a/src/lbdata.hh b/src/lbdata.hh
index 53f6cde..39115a6 100644
--- a/src/lbdata.hh
+++ b/src/lbdata.hh
@@ -84,11 +84,16 @@ public:
**/
class LBTest {
public:
- LBTest(bool debug) : _debug(debug) {}
+ typedef enum {K_NONE,K_SUCCESS,K_FAILURE} TestState;
+public:
+ LBTest(bool debug) :
+ _debug(debug),
+ _state(K_NONE)
+ {}
virtual ~LBTest() {}
virtual void
- init() = 0;
+ init();
virtual void
send(LBHealth &health) = 0;
@@ -96,10 +101,18 @@ public:
virtual int
recv(LBHealth &health) = 0;
+ virtual string
+ dump() = 0;
+
public:
bool _debug;
string _target;
int _resp_time;
+ int _state;
+ static int _recv_icmp_sock;
+ static int _send_raw_sock;
+ static int _send_icmp_sock;
+ static bool _initialized;
};
/**
diff --git a/src/lbdatafactory.cc b/src/lbdatafactory.cc
index a00887b..f230f4f 100644
--- a/src/lbdatafactory.cc
+++ b/src/lbdatafactory.cc
@@ -17,6 +17,7 @@
#include "rl_str_proc.hh"
#include "lbdata.hh"
#include "lbtest_icmp.hh"
+#include "lbtest_ttl.hh"
#include "lbdatafactory.hh"
using namespace std;
@@ -154,6 +155,9 @@ LBDataFactory::process(const vector<string> &path, int depth, const string &key,
else if (depth == 4 && key == "resp-time") {
process_health_interface_rule_type_resptime(l_key,l_value);
}
+ else if (depth == 4 && key == "ttl") {
+ process_health_interface_rule_type_udp(l_key,l_value);
+ }
}
else if (path[0] == "rule") {
if (depth > 0 && path[1] == "source") {
@@ -263,25 +267,38 @@ LBDataFactory::process_health_interface(const string &key, const string &value)
void
LBDataFactory::process_health_interface_rule_type_target(const string &key, const string &value)
{
- _test_iter->second->_target = value;
+ if (_test_iter != _health_iter->second._test_coll.end()) {
+ _test_iter->second->_target = value;
+ }
}
void
LBDataFactory::process_health_interface_rule_type_resptime(const string &key, const string &value)
{
- _test_iter->second->_resp_time = strtoul(value.c_str(), NULL, 10);
+ if (_test_iter != _health_iter->second._test_coll.end()) {
+ _test_iter->second->_resp_time = strtoul(value.c_str(), NULL, 10);
+ }
}
void
-LBDataFactory::process_health_interface_rule_type_ttl(const string &key, const string &value)
+LBDataFactory::process_health_interface_rule_type_udp(const string &key, const string &value)
{
- //nothing yet
+ if (_test_iter != _health_iter->second._test_coll.end()) {
+ if (key == "ttl") {
+ unsigned short val = (unsigned short)strtol(value.c_str(),NULL,10);
+ ((LBTestTTL*)_test_iter->second)->set_ttl(val);
+ }
+ else if (key == "port") {
+ unsigned short val = (unsigned short)strtol(value.c_str(),NULL,10);
+ ((LBTestTTL*)_test_iter->second)->set_port(val);
+ }
+ }
}
void
LBDataFactory::process_health_interface_rule_type(const string &key, const string &value)
{
- if (value == "icmp") {
+ if (value == "ping") {
if (_debug) {
cout << "LBDataFactory::process_health_interface_rule_type(): setting up icmp test" << endl;
}
@@ -289,10 +306,8 @@ LBDataFactory::process_health_interface_rule_type(const string &key, const strin
_health_iter->second._test_coll.insert(pair<int,LBTest*>(_current_test_rule_number,test));
}
else if (value == "udp") {
- /*
- LBTestUDP test = new LBTestUDP();
- _health_iter->second._test_coll.insert(pair<int,LBTest>(_current_test_rule_number,test));
- */
+ LBTestTTL *test = new LBTestTTL(_debug);
+ _health_iter->second._test_coll.insert(pair<int,LBTest*>(_current_test_rule_number,test));
}
_test_iter = _health_iter->second._test_coll.find(_current_test_rule_number);
}
diff --git a/src/lbdatafactory.hh b/src/lbdatafactory.hh
index 74b2df6..2901f72 100644
--- a/src/lbdatafactory.hh
+++ b/src/lbdatafactory.hh
@@ -68,7 +68,7 @@ private:
process_health_interface_rule_type_resptime(const string &key, const string &value);
void
- process_health_interface_rule_type_ttl(const string &key, const string &value);
+ process_health_interface_rule_type_udp(const string &key, const string &value);
void
process_rule(const string &key, const string &value);
diff --git a/src/lboutput.cc b/src/lboutput.cc
index 3ad37e1..10283d6 100644
--- a/src/lboutput.cc
+++ b/src/lboutput.cc
@@ -79,7 +79,15 @@ LBOutput::write(const LBData &lbdata)
}
}
- line += space + string("Target: Ping ") + target + "\n";
+ if (titer->second->_state == LBTest::K_NONE) {
+ line += space + string("*Target: ") + target + "\n";
+ }
+ else if (titer->second->_state == LBTest::K_FAILURE) {
+ line += space + string("-Target: ") + target + "\n";
+ }
+ else if (titer->second->_state == LBTest::K_SUCCESS) {
+ line += space + string("+Target: ") + target + "\n";
+ }
++titer;
}
diff --git a/src/lbtest_icmp.cc b/src/lbtest_icmp.cc
index c032b42..645aeed 100644
--- a/src/lbtest_icmp.cc
+++ b/src/lbtest_icmp.cc
@@ -11,6 +11,7 @@
#include <sys/sysinfo.h>
#include <unistd.h>
#include <sys/socket.h>
+#include <netdb.h>
#include <netinet/udp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -25,7 +26,6 @@
#include <iostream>
#include <string>
#include <algorithm>
-
#include "lbdata.hh"
#include "lbtest_icmp.hh"
@@ -40,52 +40,10 @@ using namespace std;
void
ICMPEngine::init()
{
- _results.erase(_results.begin(),_results.end());
- if (_initialized == true) {
- return;
- }
- _initialized = true;
if (_debug) {
cout << "LBTestICMP::init(): initializing test system" << endl;
}
-
- struct protoent *ppe = getprotobyname("icmp");
- _send_sock = socket(PF_INET, SOCK_RAW, ppe->p_proto);
- if (_send_sock < 0){
- if (_debug) {
- cerr << "LBTestICMP::LBTestICMP(): no send sock: " << _send_sock << endl;
- }
- syslog(LOG_ERR, "wan_lb: failed to acquired socket");
- _send_sock = 0;
- return;
- }
-
- //set options for broadcasting.
- int val = 1;
- setsockopt(_send_sock, SOL_SOCKET, SO_BROADCAST, &val, 4);
- setsockopt(_send_sock, SOL_SOCKET, SO_REUSEADDR, &val, 4);
-
- struct sockaddr_in addr;
- memset( &addr, 0, sizeof( struct sockaddr_in ));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = 0;
-
- _recv_sock = socket(PF_INET, SOCK_RAW, ppe->p_proto);
- if (_recv_sock < 0) {
- if (_debug) {
- cerr << "LBTestICMP::LBTestICMP(): no recv sock: " << _recv_sock << endl;
- }
- syslog(LOG_ERR, "wan_lb: failed to acquired socket");
- _recv_sock = 0;
- return;
- }
- if (bind(_recv_sock, (struct sockaddr*)&addr, sizeof(addr))==-1) {
- if (_debug) {
- cerr << "failed on bind" << endl;
- }
- syslog(LOG_ERR, "wan_lb: failed to bind recv sock");
- }
+ _results.erase(_results.begin(),_results.end());
}
/**
@@ -114,7 +72,7 @@ ICMPEngine::process(LBHealth &health,LBTestICMP *data)
cout << "LBTestICMP::start(): sending ping test for: " << health._interface << " for " << target << endl;
}
_packet_id = ++_packet_id % 32767;
- send(health._interface, target, _packet_id);
+ send(data->_send_icmp_sock, health._interface, target, _packet_id);
_results.insert(pair<int,PktData>(_packet_id,PktData(health._interface,-1)));
}
@@ -127,6 +85,10 @@ ICMPEngine::recv(LBHealth &health,LBTestICMP *data)
{
struct timeval send_time;
gettimeofday(&send_time,NULL);
+
+ if (_results.empty() == true) {
+ return -1;
+ }
//use gettimeofday to calculate time to millisecond
//then iterate over recv socket and receive and record
@@ -137,10 +99,11 @@ ICMPEngine::recv(LBHealth &health,LBTestICMP *data)
unsigned long timeout = si.uptime + 5; //seconds
unsigned long cur_time = si.uptime;
while (cur_time < timeout) {
- int id = receive();
+ int id = receive(data->_recv_icmp_sock);
if (_debug) {
cout << "LBTestICMP::start(): " << id << endl;
}
+
//update current time for comparison
struct sysinfo si;
sysinfo(&si);
@@ -162,9 +125,11 @@ ICMPEngine::recv(LBHealth &health,LBTestICMP *data)
//time in milliseconds below
int rtt = abs(msecs) / 1000 + 1000 * secs;
if (rtt < data->_resp_time) {
- return rtt;
+ data->_state = LBTest::K_SUCCESS;
+ return rtt;
}
else {
+ data->_state = LBTest::K_FAILURE;
return -1;
}
_results.erase(r_iter);
@@ -174,20 +139,16 @@ ICMPEngine::recv(LBHealth &health,LBTestICMP *data)
if (_debug) {
cout << "LBTestICMP::start(): finished heath test" << endl;
}
+ data->_state = LBTest::K_FAILURE;
return -1;
}
-
-
-
-
-
/**
*
*
**/
void
-ICMPEngine::send(const string &iface, const string &target_addr, int packet_id)
+ICMPEngine::send(int send_sock, const string &iface, const string &target_addr, int packet_id)
{
int err;
sockaddr_in taddr;
@@ -200,12 +161,6 @@ ICMPEngine::send(const string &iface, const string &target_addr, int packet_id)
return;
}
- // bind a socket to a device name (might not work on all systems):
- if (setsockopt(_send_sock, SOL_SOCKET, SO_BINDTODEVICE, iface.c_str(), iface.size()) != 0) {
- syslog(LOG_ERR, "wan_lb: failure to bind to interface: %s", iface.c_str());
- return; //will allow the test to time out then
- }
-
//convert target_addr to ip addr
struct hostent *h = gethostbyname(target_addr.c_str());
if (h == NULL) {
@@ -216,6 +171,12 @@ ICMPEngine::send(const string &iface, const string &target_addr, int packet_id)
return;
}
+ // bind a socket to a device name (might not work on all systems):
+ if (setsockopt(send_sock, SOL_SOCKET, SO_BINDTODEVICE, iface.c_str(), iface.size()) != 0) {
+ syslog(LOG_ERR, "wan_lb: failure to bind to interface: %s", iface.c_str());
+ return; //will allow the test to time out then
+ }
+
icmp_hdr = (struct icmphdr *)buffer;
icmp_hdr->type = ICMP_ECHO;
icmp_hdr->code = 0;
@@ -250,12 +211,11 @@ ICMPEngine::send(const string &iface, const string &target_addr, int packet_id)
bzero(&(taddr.sin_zero), 8);
//need to direct this packet out a specific interface!!!!!!!!!!!!!
- err = sendto(_send_sock, buffer, icmp_pktsize, 0, (struct sockaddr*)&taddr, sizeof(taddr));
+ err = sendto(send_sock, buffer, icmp_pktsize, 0, (struct sockaddr*)&taddr, sizeof(taddr));
if (_debug) {
cout << "LBTestICMP::send(): sendto: " << err << ", packet id: " << packet_id << endl;
}
- if(err < 0)
- {
+ if(err < 0) {
if (_debug) {
if (errno == EBADF)
cout << "EBADF" << endl;
@@ -293,7 +253,7 @@ ICMPEngine::send(const string &iface, const string &target_addr, int packet_id)
*
**/
int
-ICMPEngine::receive()
+ICMPEngine::receive(int recv_sock)
{
int icmp_pktsize = 40;
char resp_buf[icmp_pktsize];
@@ -303,7 +263,7 @@ ICMPEngine::receive()
int ret;
FD_ZERO(&readfs);
- FD_SET(_recv_sock, &readfs);
+ FD_SET(recv_sock, &readfs);
wait_time.tv_usec = 0;
wait_time.tv_sec = 3; //3 second timeout
@@ -312,27 +272,25 @@ ICMPEngine::receive()
cout << "LBTestICMP::receive(): start" << endl;
}
- while (select(_recv_sock+1, &readfs, NULL, NULL, &wait_time) != 0)
+ while (select(recv_sock+1, &readfs, NULL, NULL, &wait_time) != 0)
{
- ret = ::recv(_recv_sock, &resp_buf, icmp_pktsize, 0);
- if (ret != -1)
- {
+ ret = ::recv(recv_sock, &resp_buf, icmp_pktsize, 0);
+ if (ret != -1) {
if (_debug) {
cout << "LBTestICMP::receive(): recv: " << ret << endl;
}
-
+
icmp_hdr = (struct icmphdr *)(resp_buf + sizeof(iphdr));
- if (icmp_hdr->type == ICMP_ECHOREPLY)
- {
+ if (icmp_hdr->type == ICMP_ECHOREPLY) {
+ //process packet data
+ char* data;
+ int id = 0;
+ data = (char*)(&resp_buf) + 36;
+ memcpy(&id, data, sizeof(unsigned short));
if (_debug) {
- cout << "LBTestICMP::receive(): " << endl;
+ cout << "LBTestICMP::receive(): " << id << endl;
}
- //process packet data
- char* data;
- int id = 0;
- data = (char*)(&resp_buf) + 36;
- memcpy(&id, data, sizeof(unsigned short));
- return id;
+ return id;
}
}
}
@@ -347,10 +305,22 @@ unsigned short
ICMPEngine::in_checksum(const unsigned short *buffer, int length) const
{
unsigned long sum;
- for (sum=0; length>0; length--)
+ for (sum=0; length>0; length--) {
sum += *buffer++;
+ }
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
+/**
+ *
+ *
+ **/
+string
+LBTestICMP::dump()
+{
+ char buf[20];
+ sprintf(buf,"%u",_resp_time);
+ return (string("target: ") + _target + ", resp_time: " + buf);
+}
diff --git a/src/lbtest_icmp.hh b/src/lbtest_icmp.hh
index 4eb94e8..ea8e893 100644
--- a/src/lbtest_icmp.hh
+++ b/src/lbtest_icmp.hh
@@ -41,8 +41,6 @@ public:
ICMPEngine() :
_debug(true),
_initialized(false),
- _send_sock(0),
- _recv_sock(0),
_packet_id(0)
{}
@@ -57,10 +55,10 @@ public:
private:
void
- send(const string &iface, const string &target_addr, int packet_id);
+ send(int sock, const string &iface, const string &target_addr, int packet_id);
int
- receive();
+ receive(int sock);
unsigned short
in_checksum(const unsigned short *buf, int lenght) const;
@@ -68,8 +66,6 @@ private:
private:
bool _debug;
bool _initialized;
- int _send_sock;
- int _recv_sock;
int _packet_id;
map<int,PktData> _results;
};
@@ -85,7 +81,7 @@ public:
~LBTestICMP() {}
void
- init() {_engine.init();}
+ init() {_engine.init();this->LBTest::init();}
void
send(LBHealth &health) {_engine.process(health,this);}
@@ -93,6 +89,9 @@ public:
int
recv(LBHealth &health) {return _engine.recv(health,this);}
+ string
+ dump();
+
private:
static ICMPEngine _engine; //singleton
bool _debug;