Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef vnsw_agent_bfd_proto_h_ 6 : #define vnsw_agent_bfd_proto_h_ 7 : 8 : #include <mutex> 9 : 10 : #include "pkt/proto.h" 11 : #include "pkt/pkt_handler.h" 12 : #include "services/bfd_handler.h" 13 : #include "oper/health_check.h" 14 : 15 : #include "bfd/bfd_client.h" 16 : #include "bfd/bfd_server.h" 17 : #include "bfd/bfd_connection.h" 18 : #include "bfd/bfd_session.h" 19 : 20 : #include "base/test/task_test_util.h" 21 : 22 : #define BFD_TX_BUFF_LEN 128 23 : 24 : #define BFD_TRACE(obj, ...) \ 25 : do { \ 26 : Bfd##obj::TraceMsg(BfdTraceBuf, __FILE__, __LINE__, ##__VA_ARGS__); \ 27 : } while (false) 28 : 29 : class BfdSessionsKey { 30 : public: 31 0 : BfdSessionsKey(uint32_t id, IpAddress ip) : 32 0 : id_(id), ip_(ip) { 33 0 : } 34 : 35 0 : ~BfdSessionsKey () { } 36 : 37 : bool operator<(const BfdSessionsKey &right) const { 38 : if ( id_ == right.id_ ) { 39 : return ip_ < right.ip_; 40 : } else { 41 : return id_ < right.id_; 42 : } 43 : } 44 : 45 : bool IsLess(const BfdSessionsKey &rhs) const; 46 : bool IsEqual(const BfdSessionsKey &rhs) const; 47 : 48 : uint32_t id_; 49 : IpAddress ip_; 50 : }; 51 : 52 : struct BfdSessionsKeyCmp { 53 0 : bool operator()(const BfdSessionsKey &lhs, const BfdSessionsKey &rhs) const { 54 0 : return lhs.IsLess(rhs); 55 : } 56 : }; 57 : 58 : class BfdProto : public Proto { 59 : public: 60 : static const uint32_t kMultiplier = 2; 61 : static const uint32_t kMinRxInterval = 500000; // microseconds 62 : static const uint32_t kMinTxInterval = 500000; // microseconds 63 : 64 : struct BfdStats { 65 1 : BfdStats() { Reset(); } 66 1 : void Reset() { bfd_sent = bfd_received = bfd_rx_drop_count = 0; 67 1 : bfd_rx_ka_enqueue_count = 0; } 68 : 69 : uint64_t bfd_sent; 70 : uint64_t bfd_received; 71 : uint32_t bfd_rx_drop_count; 72 : uint64_t bfd_rx_ka_enqueue_count; 73 : }; 74 : 75 : class BfdCommunicator : public BFD::Connection { 76 : public: 77 1 : BfdCommunicator(BfdProto *bfd_proto) : 78 1 : bfd_proto_(bfd_proto), server_(NULL) {} 79 1 : virtual ~BfdCommunicator() {} 80 : virtual void SendPacket( 81 : const boost::asio::ip::udp::endpoint &local_endpoint, 82 : const boost::asio::ip::udp::endpoint &remote_endpoint, 83 : const BFD::SessionIndex &session_index, 84 : const boost::asio::mutable_buffer &packet, int pktSize); 85 : virtual void NotifyStateChange(const BFD::SessionKey &key, const bool &up); 86 0 : virtual BFD::Server *GetServer() const { return server_; } 87 1 : virtual void SetServer(BFD::Server *server) { server_ = server; } 88 : 89 : private: 90 : BfdProto *bfd_proto_; 91 : BFD::Server *server_; 92 : }; 93 : 94 : BfdProto(Agent *agent, boost::asio::io_context &io); 95 : virtual ~BfdProto(); 96 : ProtoHandler *AllocProtoHandler(boost::shared_ptr<PktInfo> info, 97 : boost::asio::io_context &io); 98 1 : void Shutdown() { 99 1 : delete client_; 100 1 : client_ = NULL; 101 : 102 : // server_->DeleteClientSessions(); 103 : // TASK_UTIL_EXPECT_TRUE(server_->event_queue()->IsQueueEmpty()); 104 1 : server_->event_queue()->Shutdown(); 105 1 : delete server_; 106 1 : server_ = NULL; 107 : 108 1 : sessions_.clear(); 109 1 : } 110 : 111 : bool Enqueue(boost::shared_ptr<PktInfo> msg); 112 : void ProcessStats(PktStatsType::Type type); 113 : bool ProcessBfdKeepAlive(boost::shared_ptr<PktInfo> msg); 114 : void HandleReceiveSafe(boost::asio::const_buffer pkt, 115 : const boost::asio::ip::udp::endpoint &local_endpoint, 116 : const boost::asio::ip::udp::endpoint &remote_endpoint, 117 : const BFD::SessionIndex &session_index, 118 : uint8_t pkt_len, 119 : boost::system::error_code ec); 120 : 121 : bool BfdHealthCheckSessionControl( 122 : HealthCheckTable::HealthCheckServiceAction action, 123 : HealthCheckInstanceService *service); 124 : void NotifyHealthCheckInstanceService(uint32_t interface, 125 : IpAddress address, std::string &data); 126 0 : BfdCommunicator &bfd_communicator() { return communicator_; } 127 : 128 0 : void IncrementSent() { stats_.bfd_sent++; } 129 0 : void IncrementReceived() { stats_.bfd_received++; } 130 0 : void IncrementReceiveDropCount() { stats_.bfd_rx_drop_count++; } 131 0 : void IncrementKaEnqueueCount() { stats_.bfd_rx_ka_enqueue_count++; } 132 0 : const BfdStats &GetStats() const { return stats_; } 133 0 : uint32_t ActiveSessions() const { return sessions_.size(); } 134 : 135 : private: 136 : friend BfdCommunicator; 137 : // map from interface id,dest-ip to health check instance service 138 : typedef std::map<BfdSessionsKey, HealthCheckInstanceService *, BfdSessionsKeyCmp> Sessions; 139 : typedef std::pair<BfdSessionsKey, HealthCheckInstanceService *> SessionsPair; 140 : 141 : std::mutex mutex_; // lock for sessions_ access between health check & BFD 142 : std::mutex rx_mutex_; // lock for BFD control & keepalive Rx data 143 : boost::shared_ptr<PktInfo> msg_; 144 : BfdCommunicator communicator_; 145 : BFD::Server *server_; 146 : BFD::Client *client_; 147 : BfdHandler handler_; 148 : Sessions sessions_; 149 : BfdStats stats_; 150 : 151 : DISALLOW_COPY_AND_ASSIGN(BfdProto); 152 : }; 153 : 154 : #endif // vnsw_agent_bfd_proto_h_