Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef SRC_BGP_BGP_PROTO_H_
7 : #define SRC_BGP_BGP_PROTO_H_
8 :
9 : #include <sstream>
10 : #include <string>
11 : #include <vector>
12 :
13 : #include "base/parse_object.h"
14 : #include "bgp/bgp_attr.h"
15 : #include "bgp/community.h"
16 :
17 : struct BgpMpNlri;
18 : class BgpPeer;
19 :
20 : class BgpProto {
21 : public:
22 : enum MessageType {
23 : OPEN = 1,
24 : UPDATE = 2,
25 : NOTIFICATION = 3,
26 : KEEPALIVE = 4
27 : };
28 :
29 : enum BgpPeerType {
30 : IBGP,
31 : EBGP,
32 : XMPP,
33 : };
34 :
35 4 : static std::string BgpPeerTypeString(BgpPeerType peer_type) {
36 4 : switch (peer_type) {
37 4 : case IBGP:
38 4 : return "IBGP";
39 : break;
40 0 : case EBGP:
41 0 : return "EBGP";
42 : break;
43 0 : case XMPP:
44 0 : return "XMPP";
45 : break;
46 : }
47 0 : assert(false);
48 : return "OTHER";
49 : }
50 :
51 : struct BgpMessage : public ParseObject {
52 405171 : explicit BgpMessage(MessageType type) : type(type) {
53 405169 : }
54 : MessageType type;
55 0 : virtual const std::string ToString() const { return ""; }
56 : };
57 :
58 : struct OpenMessage : public BgpMessage {
59 : enum OpenOptParamTypes {
60 : OPEN_OPT_CAPABILITIES = 2,
61 : };
62 :
63 : OpenMessage();
64 : ~OpenMessage();
65 : int Validate(BgpPeer *peer) const;
66 : uint32_t as_num;
67 : int32_t holdtime;
68 : uint32_t identifier;
69 :
70 : struct Capability : public ParseObject {
71 : enum CapabilityCode {
72 : Reserved = 0,
73 : MpExtension = 1,
74 : RouteRefresh = 2,
75 : OutboundRouteFiltering = 3,
76 : MultipleRoutesToADestination = 4,
77 : ExtendedNextHop = 5,
78 : GracefulRestart = 64,
79 : AS4Support = 65,
80 : Dynamic = 67,
81 : MultisessionBgp = 68,
82 : AddPath = 69,
83 : EnhancedRouteRefresh = 70,
84 : LongLivedGracefulRestart = 71,
85 : RouteRefreshCisco = 128
86 : };
87 33173 : static std::string CapabilityToString(int capability) {
88 33173 : switch (capability) {
89 0 : case Reserved:
90 0 : return "Reserved";
91 21304 : case MpExtension:
92 21304 : return "MpExtension";
93 122 : case RouteRefresh:
94 122 : return "RouteRefresh";
95 0 : case OutboundRouteFiltering:
96 0 : return "OutboundRouteFiltering";
97 0 : case MultipleRoutesToADestination:
98 0 : return "MultipleRoutesToADestination";
99 0 : case ExtendedNextHop:
100 0 : return "ExtendedNextHop";
101 6585 : case GracefulRestart:
102 6585 : return "GracefulRestart";
103 122 : case AS4Support:
104 122 : return "AS4Support";
105 0 : case Dynamic:
106 0 : return "Dynamic";
107 0 : case MultisessionBgp:
108 0 : return "MultisessionBgp";
109 0 : case AddPath:
110 0 : return "AddPath";
111 0 : case EnhancedRouteRefresh:
112 0 : return "EnhancedRouteRefresh";
113 4918 : case LongLivedGracefulRestart:
114 4918 : return "LongLivedGracefulRestart";
115 122 : case RouteRefreshCisco:
116 122 : return "RouteRefreshCisco";
117 : }
118 :
119 0 : std::ostringstream oss;
120 0 : oss << "Unknown(" << capability << ")";
121 0 : return oss.str();
122 : }
123 23641 : Capability() : code(Reserved) { }
124 434221 : explicit Capability(int code, const uint8_t *src, int size) :
125 434221 : code(code), capability(src, src + size) {}
126 :
127 : struct GR {
128 : enum Flags {
129 : ForwardingStatePreservedFlag = 0x80,
130 : RestartedFlag = 0x8000,
131 : NotificationFlag = 0x4000,
132 : RestartTimeMask = 0x0FFF,
133 : };
134 213689 : explicit GR() { Initialize(); }
135 1429786 : void Initialize() {
136 1429786 : flags = 0;
137 1429786 : time = 0;
138 1429786 : families.clear();
139 1429786 : }
140 : struct Family {
141 610613 : Family(uint16_t afi, uint8_t safi, uint8_t flags) :
142 610613 : afi(afi), safi(safi), flags(flags) { }
143 : uint16_t afi;
144 : uint8_t safi;
145 : uint8_t flags;
146 :
147 19505 : bool forwarding_state_preserved() const {
148 19505 : return (flags & ForwardingStatePreservedFlag) != 0;
149 : }
150 : };
151 : static Capability *Encode(uint16_t gr_time, bool restarted,
152 : bool notification,
153 : const std::vector<uint8_t> &gr_afi_flags,
154 : const std::vector<Address::Family> &gr_families);
155 : static bool Decode(GR *gr_params,
156 : const std::vector<Capability *> &capabilities);
157 : static void GetFamilies(const GR &gr_params,
158 : std::vector<std::string> *families);
159 8 : bool restarted() const { return (flags & RestartedFlag) != 0; }
160 2527 : bool notification() const {
161 2527 : return (flags & NotificationFlag) != 0;
162 : }
163 405131 : void set_flags(uint16_t gr_cap_bytes) {
164 405131 : flags = gr_cap_bytes & ~RestartTimeMask;
165 405131 : }
166 405131 : void set_time(uint16_t gr_cap_bytes) {
167 405131 : time = gr_cap_bytes & RestartTimeMask;
168 405131 : }
169 : uint16_t flags;
170 : uint16_t time;
171 : std::vector<Family> families;
172 : };
173 :
174 : struct LLGR {
175 : enum {
176 : ForwardingStatePreservedFlag = 0x80,
177 : RestartTimeMask = 0x00FFFFFF,
178 : };
179 213688 : explicit LLGR() { Initialize(); }
180 1424152 : void Initialize() {
181 1424152 : time = 0;
182 1424152 : families.clear();
183 1424152 : }
184 : struct Family {
185 610595 : Family(uint16_t afi, uint8_t safi, uint8_t flags,
186 610595 : uint32_t time) :
187 610595 : afi(afi), safi(safi), flags(flags), time(time) {
188 610595 : }
189 : uint16_t afi;
190 : uint8_t safi;
191 : uint8_t flags;
192 : uint32_t time; // 24 bits only
193 :
194 19293 : bool forwarding_state_preserved() const {
195 19293 : return (flags & ForwardingStatePreservedFlag) != 0;
196 : }
197 : };
198 :
199 : static Capability *Encode(uint32_t llgr_time,
200 : uint8_t llgr_afi_flags,
201 : const std::vector<Address::Family> &llgr_families);
202 : static bool Decode(LLGR *llgr_params,
203 : const std::vector<Capability *> &capabilities);
204 : static void GetFamilies(const LLGR &llgr_params,
205 : std::vector<std::string> *families);
206 : uint32_t time;
207 : std::vector<Family> families;
208 : };
209 :
210 : int code;
211 : std::vector<uint8_t> capability;
212 : };
213 :
214 : struct OptParam : public ParseObject {
215 31877 : ~OptParam() {
216 15938 : STLDeleteValues(&capabilities);
217 31878 : }
218 : std::vector<Capability *> capabilities;
219 : };
220 : std::vector<OptParam *> opt_params;
221 : static BgpProto::OpenMessage *Decode(const uint8_t *data, size_t size);
222 : static int EncodeData(OpenMessage *msg, uint8_t *data, size_t size);
223 : virtual const std::string ToString() const;
224 :
225 : private:
226 : int ValidateCapabilities(BgpPeer *peer) const;
227 : int EncodeCapabilities(OpenMessage *msg, uint8_t *data, size_t size);
228 : };
229 :
230 : struct Notification : public BgpMessage {
231 : enum Code {
232 : MsgHdrErr = 1,
233 : OpenMsgErr = 2,
234 : UpdateMsgErr = 3,
235 : HoldTimerExp = 4,
236 : FSMErr = 5,
237 : Cease = 6
238 : };
239 : static std::string CodeToString(Code code) {
240 : switch (code) {
241 : case MsgHdrErr:
242 : return "Message Header Error";
243 : case OpenMsgErr:
244 : return "OPEN Message Error";
245 : case UpdateMsgErr:
246 : return "UPDATE Message Error";
247 : case HoldTimerExp:
248 : return "Hold Timer Expired";
249 : case FSMErr:
250 : return "Finite State Machine Error";
251 : case Cease:
252 : return "Cease";
253 : }
254 :
255 : std::ostringstream oss;
256 : oss << "Unknown(" << code << ")";
257 : return oss.str();
258 : }
259 : enum MsgHdrSubCode {
260 : ConnNotSync = 1,
261 : BadMsgLength = 2,
262 : BadMsgType = 3,
263 : };
264 10 : static std::string MsgHdrSubcodeToString(MsgHdrSubCode sub_code) {
265 10 : switch (sub_code) {
266 0 : case ConnNotSync:
267 0 : return "Connection Not Synchronized";
268 0 : case BadMsgLength:
269 0 : return "Bad Message Length";
270 0 : case BadMsgType:
271 0 : return "Bad Message Type";
272 : }
273 :
274 20 : std::ostringstream oss;
275 10 : oss << "Unknown(" << sub_code << ")";
276 10 : return oss.str();
277 : }
278 : enum OpenMsgSubCode {
279 : UnsupportedVersion = 1,
280 : BadPeerAS = 2,
281 : BadBgpId = 3,
282 : UnsupportedOptionalParam = 4,
283 : AuthenticationFailure = 5,
284 : UnacceptableHoldTime = 6,
285 : UnsupportedCapability = 7
286 : };
287 267 : static std::string OpenMsgSubcodeToString(OpenMsgSubCode sub_code) {
288 267 : switch (sub_code) {
289 0 : case UnsupportedVersion:
290 0 : return "Unsupported Version Number";
291 222 : case BadPeerAS:
292 222 : return "Bad Peer AS";
293 8 : case BadBgpId:
294 8 : return "Bad BGP Identifier";
295 0 : case UnsupportedOptionalParam:
296 0 : return "Unsupported Optional Parameter";
297 0 : case AuthenticationFailure:
298 0 : return "Authentication Failure";
299 0 : case UnacceptableHoldTime:
300 0 : return "Unacceptable Hold Time";
301 27 : case UnsupportedCapability:
302 27 : return "Unsupported Capability";
303 : }
304 :
305 20 : std::ostringstream oss;
306 10 : oss << "Unknown(" << sub_code << ")";
307 10 : return oss.str();
308 : }
309 : enum UpdateMsgSubCode {
310 : MalformedAttributeList = 1,
311 : UnrecognizedWellKnownAttrib = 2,
312 : MissingWellKnownAttrib = 3,
313 : AttribFlagsError = 4,
314 : AttribLengthError = 5,
315 : InvalidOrigin = 6,
316 : InvalidNH = 8,
317 : OptionalAttribError = 9,
318 : InvalidNetworkField = 10,
319 : MalformedASPath = 11
320 : };
321 10 : static std::string UpdateMsgSubCodeToString(UpdateMsgSubCode sub_code) {
322 10 : switch (sub_code) {
323 0 : case MalformedAttributeList:
324 0 : return "Malformed Attribute List";
325 0 : case UnrecognizedWellKnownAttrib:
326 0 : return "Unrecognized Well-known Attribute";
327 0 : case MissingWellKnownAttrib:
328 0 : return "Missing Well-known Attribute";
329 0 : case AttribFlagsError:
330 0 : return "Attribute Flags Error";
331 0 : case AttribLengthError:
332 0 : return "Attribute Length Error";
333 0 : case InvalidOrigin:
334 0 : return "Invalid ORIGIN Attribute";
335 0 : case InvalidNH:
336 0 : return "Invalid NEXT_HOP Attribute";
337 0 : case OptionalAttribError:
338 0 : return "Optional Attribute Error";
339 0 : case InvalidNetworkField:
340 0 : return "Invalid Network Field";
341 0 : case MalformedASPath:
342 0 : return "Malformed AS_PATH";
343 : }
344 :
345 20 : std::ostringstream oss;
346 10 : oss << "Unknown(" << sub_code << ")";
347 10 : return oss.str();
348 : }
349 : enum FsmSubcode {
350 : UnspecifiedError = 0,
351 : OpenSentError = 1,
352 : OpenConfirmError = 2,
353 : EstablishedError = 3
354 : };
355 22 : static std::string FsmSubcodeToString(FsmSubcode sub_code) {
356 22 : switch (sub_code) {
357 22 : case UnspecifiedError:
358 22 : return "Unspecified Error";
359 0 : case OpenSentError:
360 0 : return "Receive Unexpected Message in OpenSent State";
361 0 : case OpenConfirmError:
362 0 : return "Receive Unexpected Message in OpenConfirm State";
363 0 : case EstablishedError:
364 0 : return "Receive Unexpected Message in Established State";
365 : }
366 :
367 0 : std::ostringstream oss;
368 0 : oss << "Unknown(" << sub_code << ")";
369 0 : return oss.str();
370 : }
371 : enum CeaseSubCode {
372 : Unknown = 0,
373 : MaxPrefixes = 1,
374 : AdminShutdown = 2,
375 : PeerDeconfigured = 3,
376 : AdminReset = 4,
377 : ConnectionRejected = 5,
378 : OtherConfigChange = 6,
379 : ConnectionCollision = 7,
380 : OutOfResources = 8,
381 : HardReset = 9,
382 : };
383 :
384 14212 : static std::string CeaseSubcodeToString(CeaseSubCode sub_code) {
385 14212 : switch (sub_code) {
386 576 : case Unknown:
387 576 : return "Unspecified Error";
388 584 : case MaxPrefixes:
389 584 : return "Received Maximum prefixes from peer";
390 4533 : case AdminShutdown:
391 4533 : return "Administrator has disabled the peer";
392 4647 : case PeerDeconfigured:
393 4647 : return "Administrator has unconfigured the peer";
394 24 : case AdminReset:
395 24 : return "Administrator reset the peer";
396 268 : case ConnectionRejected:
397 268 : return "Connection is rejected by the peer";
398 1101 : case OtherConfigChange:
399 1101 : return "Peer configuration has changed";
400 2462 : case ConnectionCollision:
401 2462 : return "Connection collision";
402 0 : case OutOfResources:
403 0 : return "Unable handle peer due to resource limit";
404 16 : case HardReset:
405 16 : return "Received HardReset to skip GR Helper mode";
406 : }
407 :
408 1 : std::ostringstream oss;
409 0 : oss << "Unknown(" << sub_code << ")";
410 0 : return oss.str();
411 : }
412 :
413 : Notification();
414 : int error;
415 : int subcode;
416 : std::string data;
417 : static BgpProto::Notification *Decode(const uint8_t *data, size_t size);
418 : static int EncodeData(Notification *msg, uint8_t *data, size_t size);
419 : virtual const std::string ToString() const;
420 : static const std::string toString(Code code, int subcode);
421 : };
422 :
423 : struct Keepalive : public BgpMessage {
424 : Keepalive();
425 : static BgpProto::Keepalive *Decode(const uint8_t *data, size_t size);
426 : };
427 :
428 : struct Update : public BgpMessage {
429 : Update();
430 : ~Update();
431 : int Validate(const BgpPeer *, std::string *data);
432 : int CompareTo(const Update &rhs) const;
433 : static BgpProto::Update *Decode(const uint8_t *data, size_t size);
434 :
435 : std::vector <BgpProtoPrefix *> withdrawn_routes;
436 : std::vector <BgpAttribute *> path_attributes;
437 : std::vector <BgpProtoPrefix *> nlri;
438 : static int EncodeData(Update *msg, uint8_t *data, size_t size);
439 : };
440 :
441 : static const int kMinMessageSize = 19;
442 : static const int kMaxMessageSize = 4096;
443 :
444 : static BgpMessage *Decode(const uint8_t *data, size_t size,
445 : ParseErrorContext *ec = NULL, bool as4 = false);
446 :
447 : static int Encode(const BgpMessage *msg, uint8_t *data, size_t size,
448 : EncodeOffsets *offsets = NULL, bool as4 = false);
449 : static int Encode(const BgpMpNlri *msg, uint8_t *data, size_t size,
450 : EncodeOffsets *offsets = NULL);
451 : };
452 :
453 : #endif // SRC_BGP_BGP_PROTO_H_
|