Commit 15560cac authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

Merge branch 'trac2231'

Conflicts:
	src/lib/dhcp/tests/iface_mgr_unittest.cc
parents 8ad1accc b7598c1b
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -820,8 +820,12 @@ IfaceMgr::send(const Pkt4Ptr& pkt)
boost::shared_ptr<Pkt4>
IfaceMgr::receive4(uint32_t timeout) {
IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
// Sanity check for microsecond timeout.
if (timeout_usec >= 1000000) {
isc_throw(BadValue, "fractional timeout must be shorter than"
" one million microseconds");
}
const SocketInfo* candidate = 0;
IfaceCollection::const_iterator iface;
fd_set sockets;
......@@ -861,13 +865,13 @@ IfaceMgr::receive4(uint32_t timeout) {
names << session_socket_ << "(session)";
}
/// @todo: implement sub-second precision one day
struct timeval select_timeout;
select_timeout.tv_sec = timeout;
select_timeout.tv_usec = 0;
select_timeout.tv_sec = timeout_sec;
select_timeout.tv_usec = timeout_usec;
cout << "Trying to receive data on sockets: " << names.str()
<< ". Timeout is " << timeout << " seconds." << endl;
<< ". Timeout is " << timeout_sec << "." << setw(6) << setfill('0')
<< timeout_usec << " seconds." << endl;
int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
cout << "select returned " << result << endl;
......@@ -990,7 +994,12 @@ IfaceMgr::receive4(uint32_t timeout) {
return (pkt);
}
Pkt6Ptr IfaceMgr::receive6(uint32_t timeout) {
Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
// Sanity check for microsecond timeout.
if (timeout_usec >= 1000000) {
isc_throw(BadValue, "fractional timeout must be shorter than"
" one million microseconds");
}
const SocketInfo* candidate = 0;
fd_set sockets;
......@@ -1030,13 +1039,13 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout) {
names << session_socket_ << "(session)";
}
cout << "Trying to receive data on sockets:" << names.str()
<< ".Timeout is " << timeout << " seconds." << endl;
cout << "Trying to receive data on sockets: " << names.str()
<< ". Timeout is " << timeout_sec << "." << setw(6) << setfill('0')
<< timeout_usec << " seconds." << endl;
/// @todo: implement sub-second precision one day
struct timeval select_timeout;
select_timeout.tv_sec = timeout;
select_timeout.tv_usec = 0;
select_timeout.tv_sec = timeout_sec;
select_timeout.tv_usec = timeout_usec;
int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -364,10 +364,13 @@ public:
/// to not wait infinitely, but rather do something useful
/// (e.g. remove expired leases)
///
/// @param timeout specifies timeout (in seconds)
/// @param timeout_sec specifies integral part of the timeout (in seconds)
/// @param timeout_usec specifies fractional part of the timeout
/// (in microseconds)
///
/// @throw isc::BadValue if timeout_usec is greater than one million
/// @return Pkt6 object representing received packet (or NULL)
Pkt6Ptr receive6(uint32_t timeout);
Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @brief Tries to receive IPv4 packet over open IPv4 sockets.
///
......@@ -375,10 +378,13 @@ public:
/// If reception is successful and all information about its sender
/// are obtained, Pkt4 object is created and returned.
///
/// @param timeout specifies timeout (in seconds)
/// @param timeout_sec specifies integral part of the timeout (in seconds)
/// @param timeout_usec specifies fractional part of the timeout
/// (in microseconds)
///
/// @throw isc::BadValue if timeout_usec is greater than one million
/// @return Pkt4 object representing received packet (or NULL)
Pkt4Ptr receive4(uint32_t timeout);
Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// Opens UDP/IP socket and binds it to address, interface and port.
///
......
......@@ -218,6 +218,106 @@ TEST_F(IfaceMgrTest, getIface) {
}
TEST_F(IfaceMgrTest, receiveTimeout6) {
using namespace boost::posix_time;
std::cout << "Testing DHCPv6 packet reception timeouts."
<< " Test will block for a few seconds when waiting"
<< " for timeout to occur." << std::endl;
boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
// Open socket on the lo interface.
IOAddress loAddr("::1");
int socket1 = 0;
ASSERT_NO_THROW(
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547)
);
// Socket is open if its descriptor is greater than zero.
ASSERT_GT(socket1, 0);
// Remember when we call receive6().
ptime start_time = microsec_clock::universal_time();
// Call receive with timeout of 1s + 400000us = 1.4s.
Pkt6Ptr pkt;
ASSERT_NO_THROW(pkt = ifacemgr->receive6(1, 400000));
// Remember when call to receive6() ended.
ptime stop_time = microsec_clock::universal_time();
// We did not send a packet to lo interface so we expect that
// nothing has been received and timeout has been reached.
ASSERT_FALSE(pkt);
// Calculate duration of call to receive6().
time_duration duration = stop_time - start_time;
// We stop the clock when the call completes so it does not
// precisely reflect the receive timeout. However the
// uncertainity should be low enough to expect that measured
// value is in the range <1.4s; 1.7s>.
EXPECT_GE(duration.total_microseconds(), 1400000);
EXPECT_LE(duration.total_microseconds(), 1700000);
// Test timeout shorter than 1s.
start_time = microsec_clock::universal_time();
ASSERT_NO_THROW(pkt = ifacemgr->receive6(0, 500000));
stop_time = microsec_clock::universal_time();
ASSERT_FALSE(pkt);
duration = stop_time - start_time;
// Check if measured duration is within <0.5s; 0.8s>.
EXPECT_GE(duration.total_microseconds(), 500000);
EXPECT_LE(duration.total_microseconds(), 800000);
// Test with invalid fractional timeout values.
EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
EXPECT_THROW(ifacemgr->receive6(1, 1000010), isc::BadValue);
}
TEST_F(IfaceMgrTest, receiveTimeout4) {
using namespace boost::posix_time;
std::cout << "Testing DHCPv6 packet reception timeouts."
<< " Test will block for a few seconds when waiting"
<< " for timeout to occur." << std::endl;
boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
// Open socket on the lo interface.
IOAddress loAddr("127.0.0.1");
int socket1 = 0;
ASSERT_NO_THROW(
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10067)
);
// Socket is open if its descriptor is greater than zero.
ASSERT_GT(socket1, 0);
Pkt4Ptr pkt;
// Remember when we call receive4().
ptime start_time = microsec_clock::universal_time();
// Call receive with timeout of 2s + 300000us = 2.3s.
ASSERT_NO_THROW(pkt = ifacemgr->receive4(2, 300000));
// Remember when call to receive4() ended.
ptime stop_time = microsec_clock::universal_time();
// We did not send a packet to lo interface so we expect that
// nothing has been received and timeout has been reached.
ASSERT_FALSE(pkt);
// Calculate duration of call to receive4().
time_duration duration = stop_time - start_time;
// We stop the clock when the call completes so it does not
// precisely reflect the receive timeout. However the
// uncertainity should be low enough to expect that measured
// value is in the range <2.3s; 2.6s>.
EXPECT_GE(duration.total_microseconds(), 2300000);
EXPECT_LE(duration.total_microseconds(), 2600000);
// Test timeout shorter than 1s.
start_time = microsec_clock::universal_time();
ASSERT_NO_THROW(pkt = ifacemgr->receive4(0, 400000));
stop_time = microsec_clock::universal_time();
ASSERT_FALSE(pkt);
duration = stop_time - start_time;
// Check if measured duration is within <0.4s; 0.7s>.
EXPECT_GE(duration.total_microseconds(), 400000);
EXPECT_LE(duration.total_microseconds(), 700000);
// Test with invalid fractional timeout values.
EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
EXPECT_THROW(ifacemgr->receive6(2, 1000005), isc::BadValue);
}
TEST_F(IfaceMgrTest, multipleSockets) {
boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment