Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
ed478d28
Commit
ed478d28
authored
Jun 22, 2012
by
Tomek Mrugalski
🛰
Browse files
[1708] Data reception over many interfaces (IPv6) added
parent
f788c425
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/dhcp6.spec
View file @
ed478d28
{
"module_spec": {
"module_name": "
d
hcp6",
"module_name": "
D
hcp6",
"module_description": "DHCPv6 server daemon",
"config_data": [
{ "item_name": "interface",
...
...
@@ -9,6 +9,18 @@
"item_default": "eth0"
}
],
"commands": []
"commands": [
{
"command_name": "shutdown",
"command_description": "Shuts down DHCPv6 server.",
"command_args": [
{
"item_name": "pid",
"item_type": "integer",
"item_optional": true
}
]
}
]
}
}
src/bin/dhcp6/dhcp6_srv.cc
View file @
ed478d28
...
...
@@ -79,9 +79,11 @@ void Dhcpv6Srv::shutdown() {
bool
Dhcpv6Srv
::
run
()
{
while
(
!
shutdown_
)
{
/// @todo: calculate actual timeout once we have lease database
int
timeout
=
1000
;
// client's message and server's response
Pkt6Ptr
query
=
IfaceMgr
::
instance
().
receive6
();
Pkt6Ptr
query
=
IfaceMgr
::
instance
().
receive6
(
timeout
);
Pkt6Ptr
rsp
;
if
(
query
)
{
...
...
src/lib/dhcp/iface_mgr.cc
View file @
ed478d28
...
...
@@ -693,13 +693,12 @@ IfaceMgr::receive4(uint32_t timeout) {
const
SocketInfo
*
candidate
=
0
;
IfaceCollection
::
const_iterator
iface
;
fd_set
sockets
;
FD_ZERO
(
&
sockets
);
int
maxfd
=
0
;
stringstream
names
;
FD_ZERO
(
&
sockets
);
/// @todo: marginal performance optimization. We could create the set once
/// and then use its copy for select(). Please note that select() modifies
/// provided set to indicated which sockets have something to read.
...
...
@@ -858,9 +857,108 @@ IfaceMgr::receive4(uint32_t timeout) {
return
(
pkt
);
}
Pkt6Ptr
IfaceMgr
::
receive6
()
{
uint8_t
buf
[
RCVBUFSIZE
];
Pkt6Ptr
IfaceMgr
::
receive6
(
uint32_t
timeout
)
{
const
SocketInfo
*
candidate
=
0
;
fd_set
sockets
;
int
maxfd
=
0
;
stringstream
names
;
FD_ZERO
(
&
sockets
);
/// @todo: marginal performance optimization. We could create the set once
/// and then use its copy for select(). Please note that select() modifies
/// provided set to indicated which sockets have something to read.
IfaceCollection
::
const_iterator
iface
;
for
(
iface
=
ifaces_
.
begin
();
iface
!=
ifaces_
.
end
();
++
iface
)
{
for
(
SocketCollection
::
const_iterator
s
=
iface
->
sockets_
.
begin
();
s
!=
iface
->
sockets_
.
end
();
++
s
)
{
// Only deal with IPv4 addresses.
if
(
s
->
addr_
.
getFamily
()
==
AF_INET6
)
{
names
<<
s
->
sockfd_
<<
"("
<<
iface
->
getName
()
<<
") "
;
// Add this socket to listening set
FD_SET
(
s
->
sockfd_
,
&
sockets
);
if
(
maxfd
<
s
->
sockfd_
)
{
maxfd
=
s
->
sockfd_
;
}
}
}
}
// if there is session socket registered...
if
(
session_socket_
!=
INVALID_SOCKET
)
{
// at it to the set as well
FD_SET
(
session_socket_
,
&
sockets
);
if
(
maxfd
<
session_socket_
)
maxfd
=
session_socket_
;
names
<<
session_socket_
<<
"(session)"
;
}
cout
<<
"Trying to receive data on sockets:"
<<
names
.
str
()
<<
".Timeout is "
<<
timeout
<<
" seconds."
<<
endl
;
/// @todo: implement sub-second precision one day
struct
timeval
select_timeout
;
select_timeout
.
tv_sec
=
timeout
;
select_timeout
.
tv_usec
=
0
;
int
result
=
select
(
maxfd
+
1
,
&
sockets
,
NULL
,
NULL
,
&
select_timeout
);
if
(
result
==
0
)
{
// nothing received and timeout has been reached
return
(
Pkt6Ptr
());
// NULL
}
else
if
(
result
<
0
)
{
cout
<<
"Socket read error: "
<<
strerror
(
errno
)
<<
endl
;
/// @todo: perhaps throw here?
return
(
Pkt6Ptr
());
// NULL
}
// Let's find out which socket has the data
if
((
session_socket_
!=
INVALID_SOCKET
)
&&
(
FD_ISSET
(
session_socket_
,
&
sockets
)))
{
// something received over session socket
cout
<<
"BIND10 command or config available over session socket."
<<
endl
;
if
(
session_callback_
)
{
// in theory we could call io_service.run_one() here, instead of
// implementing callback mechanism, but that would introduce
// asiolink dependency to libdhcp++ and that is something we want
// to avoid (see CPE market and out long term plans for minimalistic
// implementations.
session_callback_
();
}
return
(
Pkt6Ptr
());
// NULL
}
// Let's find out which interface/socket has the data
for
(
iface
=
ifaces_
.
begin
();
iface
!=
ifaces_
.
end
();
++
iface
)
{
for
(
SocketCollection
::
const_iterator
s
=
iface
->
sockets_
.
begin
();
s
!=
iface
->
sockets_
.
end
();
++
s
)
{
if
(
FD_ISSET
(
s
->
sockfd_
,
&
sockets
))
{
candidate
=
&
(
*
s
);
break
;
}
}
if
(
candidate
)
{
break
;
}
}
if
(
!
candidate
)
{
cout
<<
"Received data over unknown socket."
<<
endl
;
return
(
Pkt6Ptr
());
// NULL
}
cout
<<
"Trying to receive over UDP6 socket "
<<
candidate
->
sockfd_
<<
" bound to "
<<
candidate
->
addr_
.
toText
()
<<
"/port="
<<
candidate
->
port_
<<
" on "
<<
iface
->
getFullName
()
<<
endl
;
// Now we have a socket, let's get some data from it!
uint8_t
buf
[
RCVBUFSIZE
];
memset
(
&
control_buf_
[
0
],
0
,
control_buf_len_
);
struct
sockaddr_in6
from
;
memset
(
&
from
,
0
,
sizeof
(
from
));
...
...
@@ -892,43 +990,7 @@ Pkt6Ptr IfaceMgr::receive6() {
m
.
msg_control
=
&
control_buf_
[
0
];
m
.
msg_controllen
=
control_buf_len_
;
/// TODO: Need to move to select() and pool over
/// all available sockets. For now, we just take the
/// first interface and use first socket from it.
IfaceCollection
::
const_iterator
iface
=
ifaces_
.
begin
();
const
SocketInfo
*
candidate
=
0
;
while
(
iface
!=
ifaces_
.
end
())
{
for
(
SocketCollection
::
const_iterator
s
=
iface
->
sockets_
.
begin
();
s
!=
iface
->
sockets_
.
end
();
++
s
)
{
if
(
s
->
addr_
.
getFamily
()
!=
AF_INET6
)
{
continue
;
}
if
(
s
->
addr_
.
getAddress
().
to_v6
().
is_multicast
())
{
candidate
=
&
(
*
s
);
break
;
}
if
(
!
candidate
)
{
candidate
=
&
(
*
s
);
// it's not multicast, but it's better than nothing
}
}
if
(
candidate
)
{
break
;
}
++
iface
;
}
if
(
iface
==
ifaces_
.
end
())
{
isc_throw
(
Unexpected
,
"No suitable IPv6 interfaces detected. Can't receive anything."
);
}
if
(
!
candidate
)
{
isc_throw
(
Unexpected
,
"Interface "
<<
iface
->
getFullName
()
<<
" does not have any sockets open."
);
}
cout
<<
"Trying to receive over UDP6 socket "
<<
candidate
->
sockfd_
<<
" bound to "
<<
candidate
->
addr_
.
toText
()
<<
"/port="
<<
candidate
->
port_
<<
" on "
<<
iface
->
getFullName
()
<<
endl
;
int
result
=
recvmsg
(
candidate
->
sockfd_
,
&
m
,
0
);
result
=
recvmsg
(
candidate
->
sockfd_
,
&
m
,
0
);
struct
in6_addr
to_addr
;
memset
(
&
to_addr
,
0
,
sizeof
(
to_addr
));
...
...
src/lib/dhcp/iface_mgr.h
View file @
ed478d28
...
...
@@ -345,8 +345,10 @@ public:
/// to not wait infinitely, but rather do something useful
/// (e.g. remove expired leases)
///
/// @param timeout specifies timeout (in seconds)
///
/// @return Pkt6 object representing received packet (or NULL)
Pkt6Ptr
receive6
();
Pkt6Ptr
receive6
(
uint32_t
timeout
);
/// @brief Tries to receive IPv4 packet over open IPv4 sockets.
///
...
...
src/lib/dhcp/tests/iface_mgr_unittest.cc
View file @
ed478d28
...
...
@@ -309,7 +309,7 @@ TEST_F(IfaceMgrTest, sendReceive6) {
EXPECT_EQ
(
true
,
ifacemgr
->
send
(
sendPkt
));
rcvPkt
=
ifacemgr
->
receive6
();
rcvPkt
=
ifacemgr
->
receive6
(
10
);
ASSERT_TRUE
(
rcvPkt
);
// received our own packet
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment