Kea 2.6.0
receiver.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <perfdhcp/receiver.h>
11
12#include <dhcp/iface_mgr.h>
13
14#include <functional>
15
16using namespace std;
17using namespace isc::dhcp;
18
19namespace isc {
20namespace perfdhcp {
21
22
23void
25 if (single_threaded_) {
26 return;
27 }
28 if (run_flag_.test_and_set()) {
29 run_flag_.clear();
30 isc_throw(isc::Unexpected, "run_flag_ should be false.");
31 }
32 recv_thread_.reset(new std::thread(std::bind(&Receiver::run, this)));
33}
34
35void
37 if (single_threaded_) {
38 return;
39 }
40
41 // If thread is running then...
42 if (run_flag_.test_and_set()) {
43 // Clear flags to order the thread to stop its main loop.
44 run_flag_.clear();
45 recv_thread_->join();
46 }
47}
48
50 if (single_threaded_) {
51 return;
52 }
53 stop();
54}
55
56
59 if (single_threaded_) {
60 // In single thread mode read packet directly from the socket and return it.
61 return readPktFromSocket();
62 } else {
63 // In multi thread mode read packet from the queue which is feed by Receiver thread.
64 std::lock_guard<std::mutex> lock(pkt_queue_mutex_);
65 if (pkt_queue_.empty()) {
66 if (ip_version_ == 4) {
67 return Pkt4Ptr();
68 } else {
69 return Pkt6Ptr();
70 }
71 }
72 auto pkt = pkt_queue_.front();
73 pkt_queue_.pop();
74 return pkt;
75 }
76}
77
78void
79Receiver::run() {
80 if (single_threaded_) {
81 isc_throw(isc::Unexpected, "run should not be invoked in single-thread mode.");
82 }
83 try {
84 // If the flag is still true receive packets.
85 while (run_flag_.test_and_set()) {
86 receivePackets();
87 }
88
89 // Clear run flag so that subsequent call to stop will not try to stop again.
90 run_flag_.clear();
91 } catch (const exception& e) {
92 cerr << "Something went wrong: " << e.what() << endl;
93 usleep(1000);
94 } catch (...) {
95 cerr << "Something went wrong" << endl;
96 usleep(1000);
97 }
98}
99
100PktPtr
101Receiver::readPktFromSocket() {
102 PktPtr pkt;
103 uint32_t timeout;
104 if (single_threaded_) {
105 // In case of single thread just check socket and if empty exit immediately
106 // to not slow down sending part.
107 timeout = 0;
108 } else {
109 // In case of multi thread wait for packets a little bit (1ms) as it is run
110 // in separate thread and do not interfere with sending thread.
111 timeout = 1000;
112 }
113 try {
114 if (ip_version_ == 4) {
115 pkt = socket_.receive4(0, timeout);
116 } else {
117 pkt = socket_.receive6(0, timeout);
118 }
119 } catch (const Exception& e) {
120 cerr << "Failed to receive DHCP packet: " << e.what() << endl;
121 }
122
123 return (pkt);
124}
125
126void
127Receiver::receivePackets() {
128 while (true) {
129 PktPtr pkt = readPktFromSocket();
130 if (!pkt) {
131 break;
132 }
133
134 // Drop the packet if not supported. Do not bother main thread about it.
135 if (pkt->getType() == DHCPOFFER || pkt->getType() == DHCPACK ||
136 pkt->getType() == DHCPV6_ADVERTISE || pkt->getType() == DHCPV6_REPLY) {
137 // Otherwise push the packet to the queue, to main thread.
138 std::lock_guard<std::mutex> lock(pkt_queue_mutex_);
139 pkt_queue_.push(pkt);
140 }
141 }
142}
143
144}
145}
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when an unexpected error condition occurs.
virtual dhcp::Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec)=0
See description of this method in PerfSocket class below.
virtual dhcp::Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec)=0
See description of this method in PerfSocket class below.
void start()
Start a receiving thread in multi-thread mode.
Definition: receiver.cc:24
void stop()
Stop a receiving thread in multi-thread mode.
Definition: receiver.cc:36
~Receiver()
Destructor.
Definition: receiver.cc:49
dhcp::PktPtr getPkt()
Get DHCP packet.
Definition: receiver.cc:58
@ DHCPV6_ADVERTISE
Definition: dhcp6.h:199
@ DHCPV6_REPLY
Definition: dhcp6.h:204
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition: pkt.h:982
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:555
@ DHCPOFFER
Definition: dhcp4.h:236
@ DHCPACK
Definition: dhcp4.h:239
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:31
Defines the logger used by the top-level component of kea-lfc.