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