Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef SRC_BGP_BGP_PEER_H__
6 : #define SRC_BGP_BGP_PEER_H__
7 :
8 : #include <boost/asio/ip/tcp.hpp>
9 : #include <boost/scoped_ptr.hpp>
10 : #include <tbb/spin_mutex.h>
11 :
12 : #include <map>
13 : #include <memory>
14 : #include <set>
15 : #include <string>
16 : #include <vector>
17 : #include <atomic>
18 :
19 : #include "base/lifetime.h"
20 : #include "base/util.h"
21 : #include "base/task_trigger.h"
22 : #include "base/timer.h"
23 : #include "base/address.h"
24 : #include "bgp/bgp_config.h"
25 : #include "bgp/bgp_debug.h"
26 : #include "bgp/bgp_peer_key.h"
27 : #include "bgp/bgp_proto.h"
28 : #include "bgp/bgp_rib_policy.h"
29 : #include "bgp/ipeer.h"
30 : #include "bgp/rtarget/rtarget_address.h"
31 : #include "bgp/state_machine.h"
32 : #include "db/db_table.h"
33 :
34 : class BgpNeighborConfig;
35 : class BgpPeerClose;
36 : class BgpPeerInfo;
37 : class BgpPeerInfoData;
38 : class BgpServer;
39 : class BgpSession;
40 : class BgpSession;
41 : class BgpNeighborResp;
42 : class BgpSandeshContext;
43 : class PeerCloseManager;
44 : class RoutingInstance;
45 :
46 : //
47 : // This contains per address family attributes.
48 : // A BgpPeer contains a vector of pointers to this structure, with an entry
49 : // for each value in Address::Family i.e. the vector can be indexed using a
50 : // Address::Family value.
51 : //
52 : struct BgpPeerFamilyAttributes {
53 : BgpPeerFamilyAttributes(const BgpNeighborConfig *config,
54 : const BgpFamilyAttributesConfig &family_config);
55 : uint8_t loop_count;
56 : uint32_t prefix_limit;
57 : uint32_t idle_timeout;
58 : IpAddress gateway_address;
59 : std::vector<std::string> default_tunnel_encap_list;
60 : };
61 :
62 : //
63 : // Comparator for BgpPeerFamilyAttributes.
64 : //
65 : struct BgpPeerFamilyAttributesCompare {
66 100079 : int operator()(const BgpPeerFamilyAttributes *lhs,
67 : const BgpPeerFamilyAttributes *rhs) const {
68 100079 : if (lhs && rhs) {
69 16667 : KEY_COMPARE(lhs->loop_count, rhs->loop_count);
70 16663 : KEY_COMPARE(lhs->prefix_limit, rhs->prefix_limit);
71 16615 : KEY_COMPARE(lhs->idle_timeout, rhs->idle_timeout);
72 16615 : KEY_COMPARE(lhs->gateway_address, rhs->gateway_address);
73 16613 : KEY_COMPARE(lhs->default_tunnel_encap_list,
74 : rhs->default_tunnel_encap_list);
75 : } else {
76 83412 : KEY_COMPARE(lhs, rhs);
77 : }
78 99992 : return 0;
79 : }
80 : };
81 :
82 : // A BGP peer along with its session and state machine.
83 : class BgpPeer : public IPeer {
84 : public:
85 : static const int kEndOfRibSendRetryTime = 1; /* seconds */
86 : static const int kRouteTargetEndOfRibTimeSecs = 30; // Seconds
87 : static const size_t kMinBufferCapacity = 4096;
88 : static const size_t kMaxBufferCapacity = 32768;
89 :
90 : typedef std::set<Address::Family> AddressFamilyList;
91 : typedef AuthenticationData::KeyType KeyType;
92 : typedef std::set<RouteTarget> RouteTargetList;
93 :
94 : BgpPeer(BgpServer *server, RoutingInstance *instance,
95 : const BgpNeighborConfig *config);
96 : virtual ~BgpPeer();
97 :
98 : // Interface methods
99 :
100 : // thread-safe
101 10616 : virtual const std::string &ToString() const { return to_str_; }
102 771952 : virtual const std::string &ToUVEKey() const { return uve_key_str_; }
103 :
104 : // Task: bgp::SendUpdate
105 : // Used to send an UPDATE message on the socket.
106 : virtual bool SendUpdate(const uint8_t *msg, size_t msgsize,
107 : const std::string *msg_str);
108 14 : virtual bool SendUpdate(const uint8_t *msg, size_t msgsize) {
109 14 : return SendUpdate(msg, msgsize, NULL);
110 : }
111 : virtual bool FlushUpdate();
112 :
113 : // Task: bgp::Config
114 : void ConfigUpdate(const BgpNeighborConfig *config);
115 : void ClearConfig();
116 :
117 : // thread: event manager thread.
118 : // Invoked from BgpServer when a session is accepted.
119 : bool AcceptSession(BgpSession *session);
120 :
121 : BgpSession *CreateSession();
122 :
123 : virtual void SetAdminState(bool down,
124 : int subcode = BgpProto::Notification::AdminShutdown);
125 :
126 : // Messages
127 :
128 : // thread: bgp::StateMachine
129 : void SendOpen(TcpSession *session);
130 :
131 : // thread: bgp::StateMachine, KA timer handler
132 : void SendKeepalive(bool from_timer);
133 :
134 : // thread: bgp::StateMachine, io::ReaderTask
135 : void SendNotification(BgpSession *, int code, int subcode = 0,
136 : const std::string &data = std::string());
137 :
138 : // thread: io::ReaderTask
139 : void ProcessUpdate(const BgpProto::Update *msg, size_t msgsize = 0);
140 :
141 : // thread: io::ReaderTask
142 : virtual bool ReceiveMsg(BgpSession *session, const u_int8_t *msg,
143 : size_t size);
144 :
145 : void StartKeepaliveTimer();
146 : bool KeepaliveTimerRunning();
147 : bool PrefixLimitIdleTimerRunning() const;
148 : void SetSendReady();
149 :
150 : // thread: io::ReaderTask
151 : bool SetCapabilities(const BgpProto::OpenMessage *msg);
152 : void ResetCapabilities();
153 :
154 : // Table registration.
155 : void RegisterAllTables();
156 :
157 : // accessors
158 885856 : virtual BgpServer *server() { return server_; }
159 2606402 : virtual BgpServer *server() const { return server_; }
160 :
161 3408 : uint32_t PeerAddress() const { return peer_key_.address(); }
162 1502 : const std::string peer_address_string() const {
163 3004 : return peer_key_.endpoint.address().to_string();
164 : }
165 79875 : const BgpPeerKey &peer_key() const { return peer_key_; }
166 1384 : uint16_t peer_port() const { return peer_port_; }
167 : std::string transport_address_string() const;
168 : std::string gateway_address_string(Address::Family family) const;
169 53423 : const std::string &peer_name() const { return peer_name_; }
170 550 : const std::string &peer_basename() const { return peer_basename_; }
171 2779 : std::string router_type() const { return router_type_; }
172 26994 : TcpSession::Endpoint endpoint() const { return endpoint_; }
173 : virtual bool CheckSplitHorizon(uint32_t cluster_id = 0,
174 : uint32_t ribout_cid = 0) const;
175 :
176 : StateMachine::State GetState() const;
177 : virtual const std::string GetStateName() const;
178 :
179 : void set_session(BgpSession *session);
180 : void clear_session();
181 : BgpSession *session();
182 :
183 45810 : uint16_t hold_time() const { return hold_time_; }
184 6462 : as_t local_as() const { return local_as_; }
185 100234 : as_t peer_as() const { return peer_as_; }
186 806 : size_t buffer_size() const { return buffer_.size(); }
187 :
188 : // The BGP Identifier in host byte order.
189 : virtual uint32_t local_bgp_identifier() const;
190 : std::string local_bgp_identifier_string() const;
191 : virtual uint32_t bgp_identifier() const;
192 : std::string bgp_identifier_string() const;
193 :
194 5 : const std::vector<std::string> &configured_families() const {
195 5 : return configured_families_;
196 : }
197 :
198 712382 : bool LookupFamily(Address::Family family) {
199 712382 : return (family_attributes_list_[family] != NULL);
200 : }
201 :
202 : bool IsFamilyNegotiated(Address::Family family);
203 169037 : RoutingInstance *GetRoutingInstance() { return rtinstance_; }
204 0 : RoutingInstance *GetRoutingInstance() const { return rtinstance_; }
205 :
206 416373 : int GetIndex() const { return index_; }
207 : int GetTaskInstance() const;
208 :
209 406969 : virtual BgpProto::BgpPeerType PeerType() const {
210 406969 : return peer_type_;
211 : }
212 6 : const string &private_as_action() const { return private_as_action_; }
213 :
214 21601 : const BgpNeighborConfig *config() const { return config_; }
215 :
216 : virtual void SetDataCollectionKey(BgpPeerInfo *peer_info) const;
217 : void FillNeighborInfo(const BgpSandeshContext *bsc, BgpNeighborResp *bnr,
218 : bool summary) const;
219 :
220 : // thread-safe
221 : bool IsDeleted() const;
222 27608 : bool IsAdminDown() const { return admin_down_; }
223 22646 : bool IsPassive() const { return passive_; }
224 : bool IsCloseInProgress() const;
225 : virtual bool IsReady() const;
226 : virtual bool IsXmppPeer() const;
227 : virtual bool CanUseMembershipManager() const;
228 0 : virtual bool IsRegistrationRequired() const { return true; }
229 : virtual time_t GetEorSendTimerElapsedTime() const;
230 147999 : virtual bool send_ready() const { return send_ready_; }
231 :
232 : void Close(bool graceful);
233 : void Clear(int subcode);
234 :
235 : virtual IPeerClose *peer_close();
236 : virtual IPeerClose *peer_close() const;
237 : virtual void UpdateCloseRouteStats(Address::Family family,
238 : const BgpPath *old_path, uint32_t path_flags) const;
239 : virtual IPeerDebugStats *peer_stats();
240 : virtual const IPeerDebugStats *peer_stats() const;
241 : void ManagedDelete();
242 : void RetryDelete();
243 : LifetimeActor *deleter();
244 : void Initialize();
245 :
246 : void NotifyEstablished(bool established);
247 :
248 : void increment_flap_count();
249 : void reset_flap_count();
250 5679 : uint64_t flap_count() const { return flap_count_; }
251 127 : uint64_t last_flap() const { return last_flap_; }
252 22088 : uint64_t total_flap_count() const { return total_flap_count_; }
253 :
254 : void DSCPUpdateCallback(uint8_t dscp_value);
255 :
256 : std::string last_flap_at() const;
257 :
258 : void inc_rx_open();
259 : void inc_rx_keepalive();
260 : void inc_rx_update();
261 : void inc_rx_notification();
262 :
263 : void inc_tx_open();
264 : void inc_tx_keepalive();
265 : void inc_tx_update();
266 : void inc_tx_notification();
267 :
268 : void inc_rx_end_of_rib();
269 : void inc_rx_route_reach(uint64_t count);
270 : void inc_rx_route_unreach(uint64_t count);
271 :
272 : void inc_tx_end_of_rib();
273 :
274 : uint64_t get_rx_keepalive() const;
275 : uint64_t get_rx_update() const;
276 : uint64_t get_rx_notification() const;
277 : uint64_t get_tx_keepalive() const;
278 : uint64_t get_tx_update() const;
279 :
280 : uint64_t get_rx_end_of_rib() const;
281 : uint64_t get_rx_route_reach() const;
282 : uint64_t get_rx_route_unreach() const;
283 : uint64_t get_rx_route_total() const;
284 :
285 : uint64_t get_tx_end_of_rib() const;
286 : uint64_t get_tx_route_reach() const;
287 : uint64_t get_tx_route_unreach() const;
288 : uint64_t get_tx_route_total() const;
289 :
290 : void inc_connect_error();
291 : void inc_connect_timer_expired();
292 : void inc_hold_timer_expired();
293 : void inc_open_error();
294 : void inc_update_error();
295 :
296 : uint64_t get_connect_error() const;
297 : uint64_t get_connect_timer_expired() const;
298 : uint64_t get_hold_timer_expired() const;
299 : uint64_t get_open_error() const;
300 : uint64_t get_update_error() const;
301 :
302 : uint64_t get_socket_reads() const;
303 : uint64_t get_socket_writes() const;
304 :
305 : static void FillBgpNeighborDebugState(BgpNeighborResp *bnr,
306 : const IPeerDebugStats *peer);
307 :
308 : bool ResumeClose();
309 : void MembershipRequestCallback(BgpTable *table);
310 :
311 930563 : virtual void UpdateTotalPathCount(int count) const {
312 930563 : total_path_count_ += count;
313 930684 : }
314 10485 : virtual int GetTotalPathCount() const { return total_path_count_; }
315 111636 : virtual bool IsAs4Supported() const { return as4_supported_; }
316 0 : virtual void ResetAs4Supported() { as4_supported_ = false; }
317 : virtual void UpdatePrimaryPathCount(int count,
318 : Address::Family family) const;
319 : virtual void ProcessPathTunnelEncapsulation(const BgpPath *path,
320 : BgpAttr *attr, ExtCommunityDB *extcomm_db, const BgpTable *table) const;
321 : virtual const std::vector<std::string> GetDefaultTunnelEncap(
322 : const Address::Family family) const;
323 239 : virtual int GetPrimaryPathCount() const { return primary_path_count_; }
324 :
325 : void RegisterToVpnTables();
326 :
327 45526 : StateMachine *state_machine() { return state_machine_.get(); }
328 : const StateMachine *state_machine() const { return state_machine_.get(); }
329 :
330 : bool GetBestAuthKeyItem(AuthenticationKey *auth_key);
331 : bool InstallAuthKeys();
332 : std::string GetInuseAuthKeyValue() const;
333 : void SetListenSocketAuthKey(const AuthenticationKey &auth_key,
334 : KeyType key_type);
335 : void ClearListenSocketAuthKey();
336 : void SetSessionSocketAuthKey(TcpSession *session);
337 : void SetSessionSocketOptionDscp(TcpSession *session);
338 : bool AttemptGRHelperMode(int code, int subcode) const;
339 : void Register(BgpTable *table, const RibExportPolicy &policy);
340 : void Register(BgpTable *table);
341 : bool EndOfRibSendTimerExpired(Address::Family family);
342 : void CustomClose();
343 6944 : const std::vector<std::string> &negotiated_families() const {
344 6944 : return negotiated_families_;
345 : }
346 : void ReceiveEndOfRIB(Address::Family family, size_t msgsize);
347 : const std::vector<BgpProto::OpenMessage::Capability *> &
348 10814 : capabilities() const {
349 10814 : return capabilities_;
350 : }
351 :
352 8139 : static const std::vector<Address::Family> &supported_families() {
353 8139 : return supported_families_;
354 : }
355 : virtual bool IsInGRTimerWaitState() const;
356 247210 : PeerCloseManager *close_manager() { return close_manager_.get(); }
357 : virtual bool IsServerStartingUp() const;
358 : bool IsCloseGraceful() const;
359 85803 : bool IsRouterTypeBGPaaS() const { return router_type_ == "bgpaas-client"; }
360 : virtual bool ProcessSession() const;
361 : void RoutingInstanceCallback(const std::string &vrf_name, int op);
362 : void ASNUpdateCallback(as_t old_asn, as_t old_local_asn);
363 :
364 : protected:
365 : virtual void SendEndOfRIBActual(Address::Family family);
366 : virtual void SendEndOfRIB(Address::Family family);
367 9567 : int membership_req_pending() const { return membership_req_pending_; }
368 : virtual bool notification() const;
369 :
370 : private:
371 : friend class BgpConfigTest;
372 : friend class BgpPeerTest;
373 : friend class BgpServerUnitTest;
374 : friend class StateMachineUnitTest;
375 :
376 : class DeleteActor;
377 : class PeerStats;
378 :
379 : struct OriginOverride {
380 : OriginOverride(const BgpNeighborConfig::OriginOverrideConfig &config);
381 : bool operator!=(const OriginOverride &rhs) const;
382 :
383 : bool origin_override;
384 : BgpAttrOrigin::OriginType origin;
385 : };
386 :
387 : typedef std::map<Address::Family, const uint8_t *> FamilyToCapabilityMap;
388 : typedef std::vector<BgpPeerFamilyAttributes *> FamilyAttributesList;
389 :
390 : size_t GetBufferCapacity() const;
391 : bool FlushUpdateUnlocked();
392 : static int Encode(const BgpMessage *msg, uint8_t *data, size_t size,
393 : EncodeOffsets *offsets = NULL, bool as4 = false);
394 : void KeepaliveTimerErrorHandler(std::string error_name,
395 : std::string error_message);
396 : virtual void StartKeepaliveTimerUnlocked();
397 : void StopKeepaliveTimerUnlocked();
398 : bool KeepaliveTimerExpired();
399 :
400 : void StartPrefixLimitIdleTimer(uint32_t plim_idle_time_msecs);
401 : void StopPrefixLimitIdleTimer();
402 : bool PrefixLimitIdleTimerExpired();
403 : void PrefixLimitIdleTimerErrorHandler(std::string error_name,
404 : std::string error_message);
405 :
406 : RibExportPolicy BuildRibExportPolicy(Address::Family family) const;
407 : void StartEndOfRibReceiveTimer(Address::Family family);
408 : bool EndOfRibReceiveTimerExpired(Address::Family family);
409 : void EndOfRibTimerErrorHandler(std::string error_name,
410 : std::string error_message);
411 : uint32_t GetEndOfRibReceiveTime(Address::Family family) const;
412 :
413 : virtual void BindLocalEndpoint(BgpSession *session);
414 : void UnregisterAllTables();
415 : void BGPPeerInfoSend(const BgpPeerInfoData &peer_info) const;
416 :
417 : virtual bool MembershipPathCallback(DBTablePartBase *tpart,
418 : BgpRoute *route, BgpPath *path);
419 : uint32_t GetPathFlags(Address::Family family, const BgpAttr *attr) const;
420 : uint32_t GetLocalPrefFromMed(uint32_t med) const;
421 : virtual bool MpNlriAllowed(uint16_t afi, uint8_t safi);
422 : virtual bool Is4ByteAsSupported() const;
423 : BgpAttrPtr GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr);
424 : template <typename TableT, typename PrefixT>
425 : void ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
426 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags);
427 : template <typename PrefixT>
428 : void ProcessNlriBgpaas(Address::Family family, DBRequest::DBOperation oper,
429 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags);
430 : void ProcessBgpaas(DBRequest::DBOperation oper,
431 : IpAddress addr, uint8_t addr_len, BgpAttrPtr attr, uint32_t flags);
432 :
433 : bool GetBestAuthKey(AuthenticationKey *auth_key, KeyType *key_type) const;
434 : bool ProcessAuthKeyChainConfig(const BgpNeighborConfig *config);
435 : void LogInstallAuthKeys(const std::string &socket_name,
436 : const std::string &oper, const AuthenticationKey &auth_key,
437 : KeyType key_type);
438 : void SetInuseAuthKeyInfo(const AuthenticationKey &key, KeyType type);
439 : void ResetInuseAuthKeyInfo();
440 :
441 : bool CheckPrefixLimits();
442 : bool ProcessFamilyAttributesConfig(const BgpNeighborConfig *config);
443 : void ProcessEndpointConfig(const BgpNeighborConfig *config);
444 :
445 : void PostCloseRelease();
446 :
447 : void FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const;
448 : void FillCloseInfo(BgpNeighborResp *resp) const;
449 : BgpAttrPtr GetRouteTargetRouteAttr() const;
450 : void BGPaaSAddRTarget(as_t as, BgpTable *table, BgpAttrPtr attr,
451 : RouteTargetList::const_iterator it);
452 : void AddRTargets(as_t as);
453 : void DeleteRTargets(as_t as);
454 : void BGPaaSDeleteRTarget(as_t as, BgpTable *table,
455 : RouteTargetList::const_iterator it);
456 : BgpTable *GetRTargetTable();
457 :
458 : std::string BytesToHexString(const u_int8_t *msg, size_t size);
459 : virtual uint32_t GetOutputQueueDepth(Address::Family family) const;
460 : virtual time_t GetRTargetTableLastUpdatedTimeStamp() const;
461 : virtual void TriggerPrefixLimitCheck() const;
462 :
463 : static const std::vector<Address::Family> supported_families_;
464 : BgpServer *server_;
465 : RoutingInstance *rtinstance_;
466 : TcpSession::Endpoint endpoint_;
467 : BgpPeerKey peer_key_;
468 : uint16_t peer_port_;
469 : std::string peer_name_;
470 : std::string peer_basename_;
471 : std::string router_type_; // bgp_schema.xsd:BgpRouterType
472 : bool peer_is_control_node_;
473 : mutable std::string to_str_;
474 : mutable std::string uve_key_str_;
475 : const BgpNeighborConfig *config_;
476 :
477 : // Global peer index
478 : int index_;
479 : TaskTrigger trigger_;
480 : Timer *prefix_limit_idle_timer_;
481 : mutable TaskTrigger prefix_limit_trigger_;
482 :
483 : // The mutex is used to protect the session, keepalive timer and the
484 : // send ready state.
485 : //
486 : // The session is accessed from the bgp::Send task and the keepalive
487 : // timer handler and gets set/cleared from the bgp::StateMachine task.
488 : //
489 : // The keepalive timer can get started from the io thread (either via
490 : // the SetSendReady callback or from the timer handler) or from the
491 : // bgp::Send task or the bgp::StateMachine task. It can get stopped
492 : // from the bgp::Send task or the bgp::StateMachine task.
493 : //
494 : // The send ready state gets modified from the bgp::Send task or from
495 : // the io thread (either via the the SetSendReady callback or from the
496 : // timer handler).
497 : //
498 : // Note that the mutex will not be heavily contended since we expect
499 : // the bgp::Send task to lock it most frequently while all other tasks
500 : // and the io thread should need to lock it once every few seconds at
501 : // most. Hence we choose a spin_mutex.
502 : tbb::spin_mutex spin_mutex_;
503 : size_t buffer_capacity_;
504 : std::vector<uint8_t> buffer_;
505 : BgpSession *session_;
506 : Timer *keepalive_timer_;
507 : Timer *eor_receive_timer_[Address::NUM_FAMILIES];
508 : Timer *eor_send_timer_[Address::NUM_FAMILIES];
509 : time_t eor_send_timer_start_time_;
510 : bool send_ready_;
511 : bool admin_down_;
512 : bool passive_;
513 : bool resolve_paths_;
514 : bool as_override_;
515 : string private_as_action_;
516 : uint32_t cluster_id_;
517 : OriginOverride origin_override_;
518 :
519 : std::atomic<int> membership_req_pending_;
520 : bool defer_close_;
521 : bool graceful_close_;
522 : bool as4_supported_;
523 : bool vpn_tables_registered_;
524 : std::vector<BgpProto::OpenMessage::Capability *> capabilities_;
525 : uint16_t hold_time_;
526 : as_t local_as_;
527 : as_t peer_as_;
528 : uint32_t local_bgp_id_; // network order
529 : uint32_t peer_bgp_id_; // network order
530 : FamilyAttributesList family_attributes_list_;
531 : mutable std::atomic<uint32_t> family_primary_path_count_[Address::NUM_FAMILIES];
532 : std::vector<std::string> configured_families_;
533 : std::vector<std::string> negotiated_families_;
534 : BgpProto::BgpPeerType peer_type_;
535 : boost::scoped_ptr<StateMachine> state_machine_;
536 : boost::scoped_ptr<BgpPeerClose> peer_close_;
537 : boost::scoped_ptr<PeerCloseManager> close_manager_;
538 : boost::scoped_ptr<PeerStats> peer_stats_;
539 : boost::scoped_ptr<DeleteActor> deleter_;
540 : LifetimeRef<BgpPeer> instance_delete_ref_;
541 : mutable std::atomic<int> total_path_count_;
542 : mutable std::atomic<int> primary_path_count_;
543 : uint64_t flap_count_;
544 : uint64_t total_flap_count_;
545 : uint64_t last_flap_;
546 : int dscp_listener_id_;
547 : AuthenticationData auth_data_;
548 : AuthenticationKey inuse_auth_key_;
549 : KeyType inuse_authkey_type_;
550 : RouteTargetList rtargets_;
551 : int asn_listener_id_;
552 : int instance_op_;
553 :
554 : DISALLOW_COPY_AND_ASSIGN(BgpPeer);
555 : };
556 :
557 : #endif // SRC_BGP_BGP_PEER_H__
|