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