diff options
author | slioch <slioch@eng-140.vyatta.com> | 2009-07-21 11:50:09 -0700 |
---|---|---|
committer | slioch <slioch@eng-140.vyatta.com> | 2009-07-21 11:50:09 -0700 |
commit | f947ef5883cd890a2cdc3e250f6790f3a630492f (patch) | |
tree | ceb0582cfb652bbef942f3a63661a3a60f9adb9a /src | |
parent | 25d9851b65fed9297caaa01b47ec6bae76d8c954 (diff) | |
download | vyatta-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.cc | 89 | ||||
-rw-r--r-- | src/lbdata.hh | 17 | ||||
-rw-r--r-- | src/lbdatafactory.cc | 33 | ||||
-rw-r--r-- | src/lbdatafactory.hh | 2 | ||||
-rw-r--r-- | src/lboutput.cc | 10 | ||||
-rw-r--r-- | src/lbtest_icmp.cc | 128 | ||||
-rw-r--r-- | src/lbtest_icmp.hh | 13 |
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; |