Line data Source code
1 : /*
2 : * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
3 : */
4 :
5 : #include "bfd/bfd_control_packet.h"
6 :
7 : #include <string>
8 : #include <list>
9 : #include <boost/mpl/list.hpp>
10 :
11 : #include "base/proto.h"
12 :
13 : namespace BFD {
14 :
15 : class VersionAndDiagnostic: public ProtoElement<VersionAndDiagnostic> {
16 : public:
17 : static const int kSize = 1;
18 :
19 : static const int kVersionBitmask = 0xE0;
20 : static const int kVersionOffset = 5;
21 : static const int kDiagnosticBitmask = 0x1F;
22 : static const int kSupportedVersion = 1;
23 :
24 124 : static bool Verifier(const ControlPacket *obj, const uint8_t *data,
25 : size_t size, ParseContext *context) {
26 124 : uint8_t value = get_value(data, 1);
27 124 : return ((value & kVersionBitmask) >>
28 : kVersionOffset == kSupportedVersion)
29 124 : && ((value & kDiagnosticBitmask) < kDiagnosticFirstInvalid);
30 : }
31 :
32 : typedef struct {
33 124 : static void set(ControlPacket *obj, uint8_t value) {
34 124 : obj->diagnostic = (Diagnostic) (value & kDiagnosticBitmask);
35 124 : }
36 :
37 124 : static uint8_t get(const ControlPacket *obj) {
38 124 : return obj->diagnostic | (kSupportedVersion << kVersionOffset);
39 : }
40 : } Setter;
41 : };
42 :
43 : class Flags: public ProtoElement<Flags> {
44 : public:
45 : static const int kSize = 1;
46 :
47 : static const int kStateBitmask = 0xC0;
48 : static const int kStateOffset = 6;
49 : static const int kPollOffset = 5;
50 : static const int kFinallOffset = 4;
51 : static const int kControlPlaneIndependentOffset = 3;
52 : static const int kAuthenticationPresentOffset = 2;
53 : static const int kDemandOffset = 1;
54 : static const int kMultipointOffset = 0;
55 :
56 : typedef struct {
57 124 : static void set(ControlPacket *obj, uint8_t value) {
58 124 : obj->state = (BFDState) ((value & kStateBitmask)
59 124 : >> kStateOffset);
60 124 : obj->poll = value & (1 << kPollOffset);
61 124 : obj->final = value & (1 << kFinallOffset);
62 124 : obj->control_plane_independent = value &
63 : (1 << kControlPlaneIndependentOffset);
64 124 : obj->authentication_present = value &
65 : (1 << kAuthenticationPresentOffset);
66 124 : obj->demand = value & (1 << kDemandOffset);
67 124 : obj->multipoint = value & (1 << kMultipointOffset);
68 124 : }
69 :
70 124 : static uint8_t get(const ControlPacket *obj) {
71 124 : return (obj->state << kStateOffset) | (obj->poll << kPollOffset)
72 124 : | (obj->final << kFinallOffset)
73 124 : | (obj->control_plane_independent
74 124 : << kControlPlaneIndependentOffset)
75 124 : | (obj->authentication_present
76 124 : << kAuthenticationPresentOffset)
77 124 : | (obj->demand << kDemandOffset)
78 124 : | (obj->multipoint << kMultipointOffset);
79 : }
80 : } Setter;
81 : };
82 :
83 : class DetectionTimeMultiplier: public ProtoElement<DetectionTimeMultiplier> {
84 : public:
85 : typedef Accessor<ControlPacket, int,
86 : &ControlPacket::detection_time_multiplier> Setter;
87 :
88 : static const int kSize = 1;
89 :
90 124 : static bool Verifier(const ControlPacket *obj, const uint8_t *data,
91 : size_t size, ParseContext *context) {
92 124 : uint8_t value = get_value(data, 1);
93 124 : return value > 0;
94 : }
95 : };
96 :
97 : class Length: public ProtoElement<Length> {
98 : public:
99 : typedef Accessor<ControlPacket, int, &ControlPacket::length> Setter;
100 :
101 : static const int kSize = 1;
102 :
103 124 : static bool Verifier(const void *obj, const uint8_t *data, size_t size,
104 : ParseContext *context) {
105 124 : uint8_t value = get_value(data, 1);
106 124 : return value == kMinimalPacketLength;
107 : }
108 : };
109 :
110 : class SenderDiscriminator: public ProtoElement<SenderDiscriminator> {
111 : public:
112 : typedef Accessor<ControlPacket, uint32_t,
113 : &ControlPacket::sender_discriminator> Setter;
114 :
115 : static const int kSize = 4;
116 :
117 124 : static bool Verifier(const ControlPacket *obj, const uint8_t *data,
118 : size_t size, ParseContext *context) {
119 124 : uint32_t value = get_value(data, 4);
120 124 : return value > 0;
121 : }
122 : };
123 :
124 : class ReceiverDiscriminator: public ProtoElement<ReceiverDiscriminator> {
125 : public:
126 : typedef Accessor<ControlPacket, uint32_t,
127 : &ControlPacket::receiver_discriminator> Setter;
128 :
129 : static const int kSize = 4;
130 : };
131 :
132 : class DesiredMinTxInterval: public ProtoElement<DesiredMinTxInterval> {
133 : public:
134 : typedef struct {
135 124 : static void set(ControlPacket *obj, uint32_t value) {
136 124 : obj->desired_min_tx_interval =
137 124 : boost::posix_time::microseconds(value);
138 124 : }
139 :
140 124 : static uint32_t get(const ControlPacket *obj) {
141 124 : return obj->desired_min_tx_interval.total_microseconds();
142 : }
143 : } Setter;
144 :
145 : static const int kSize = 4;
146 : };
147 :
148 : class RequiredMinRxInterval: public ProtoElement<RequiredMinRxInterval> {
149 : public:
150 : typedef struct {
151 124 : static void set(ControlPacket *obj, uint32_t value) {
152 124 : obj->required_min_rx_interval =
153 124 : boost::posix_time::microseconds(value);
154 124 : }
155 :
156 124 : static uint32_t get(const ControlPacket *obj) {
157 124 : return obj->required_min_rx_interval.total_microseconds();
158 : }
159 : } Setter;
160 :
161 : static const int kSize = 4;
162 : };
163 :
164 : class RequiredMinEchoRXInterval :
165 : public ProtoElement<RequiredMinEchoRXInterval> {
166 : public:
167 : typedef struct {
168 124 : static void set(ControlPacket *obj, uint32_t value) {
169 124 : obj->required_min_echo_rx_interval =
170 124 : boost::posix_time::microseconds(value);
171 124 : }
172 :
173 124 : static uint32_t get(const ControlPacket *obj) {
174 124 : return obj->required_min_echo_rx_interval.total_microseconds();
175 : }
176 : } Setter;
177 :
178 : static const int kSize = 4;
179 : };
180 :
181 : class ControlPacketMessage: public ProtoSequence<ControlPacketMessage> {
182 : public:
183 : typedef mpl::list<VersionAndDiagnostic, Flags, DetectionTimeMultiplier,
184 : Length, SenderDiscriminator, ReceiverDiscriminator,
185 : DesiredMinTxInterval, RequiredMinRxInterval,
186 : RequiredMinEchoRXInterval> Sequence;
187 : };
188 :
189 2 : std::string ControlPacket::toString() const {
190 2 : std::ostringstream out;
191 2 : out << "Length: " << length << "\n";
192 2 : out << "Diagnostic: " << diagnostic << "\n";
193 2 : out << "State: " << state << "\n";
194 2 : out << "Poll: " << poll << "\n";
195 2 : out << "Final: " << final << "\n";
196 2 : out << "ControlPlaneIndependent: " << control_plane_independent << "\n";
197 2 : out << "AuthenticationPresent: " << authentication_present << "\n";
198 2 : out << "Demand: " << demand << "\n";
199 2 : out << "Multipoint: " << multipoint << "\n";
200 2 : out << "DetectionTimeMultiplier: " << detection_time_multiplier << "\n";
201 2 : out << "SenderDiscriminator: 0x"
202 2 : << std::hex << sender_discriminator << "\n";
203 2 : out << "ReceiverDiscriminator: 0x" << std::hex << receiver_discriminator
204 2 : << "\n";
205 2 : out << "DesiredMinTxInterval: " << desired_min_tx_interval << "\n";
206 2 : out << "RequiredMinRxInterval: " << required_min_rx_interval << "\n";
207 : out << "RequiredMinEchoRXInterval: "
208 2 : << required_min_echo_rx_interval << "\n";
209 4 : return out.str();
210 2 : }
211 :
212 118 : ResultCode ControlPacket::Verify() const {
213 118 : if (multipoint)
214 0 : return kResultCode_InvalidPacket;
215 :
216 118 : if (authentication_present)
217 0 : return kResultCode_NotImplemented;
218 :
219 118 : if (receiver_discriminator == 0 && state == kUp)
220 0 : return kResultCode_InvalidPacket;
221 :
222 118 : if (poll && final)
223 0 : return kResultCode_InvalidPacket;
224 :
225 118 : return kResultCode_Ok;
226 : }
227 :
228 124 : ControlPacket* ParseControlPacket(const uint8_t *data, size_t size) {
229 124 : ParseContext context;
230 124 : int result = ControlPacketMessage::Parse(data, size, &context,
231 124 : new ControlPacket());
232 124 : if (result < 0 || (size_t)result != size) {
233 0 : return NULL;
234 : }
235 124 : return static_cast<ControlPacket *>(context.release());
236 124 : }
237 :
238 124 : int EncodeControlPacket(const ControlPacket *msg, uint8_t *data, size_t size) {
239 124 : EncodeContext context;
240 248 : return ControlPacketMessage::Encode(&context, msg, data, size);
241 124 : }
242 :
243 1 : bool operator==(const ControlPacket &p1, const ControlPacket &p2) {
244 1 : return p1.poll == p2.poll && p1.final == p2.final
245 1 : && p1.control_plane_independent == p2.control_plane_independent
246 1 : && p1.authentication_present == p2.authentication_present
247 1 : && p1.demand == p2.demand && p1.multipoint == p2.multipoint
248 1 : && p1.detection_time_multiplier == p2.detection_time_multiplier
249 1 : && p1.length == p2.length
250 1 : && p1.sender_discriminator == p2.sender_discriminator
251 1 : && p1.receiver_discriminator == p2.receiver_discriminator
252 1 : && p1.diagnostic == p2.diagnostic && p1.state == p2.state
253 1 : && p1.desired_min_tx_interval == p2.desired_min_tx_interval
254 1 : && p1.required_min_rx_interval == p2.required_min_rx_interval
255 2 : && p1.required_min_echo_rx_interval ==
256 1 : p2.required_min_echo_rx_interval;
257 : }
258 : } // namespace BFD
|