Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef vnsw_agent_igmp_proto_hpp 6 : #define vnsw_agent_igmp_proto_hpp 7 : 8 : #include "pkt/proto.h" 9 : #include "services/igmp_handler.h" 10 : 11 : #include "services/multicast/gmp_map/gmp_proto.h" 12 : 13 : #define IGMP_UNDEFINED 0x10 14 : #define IGMP_MEMBERSHIP_QUERY 0x11 15 : #define IGMP_V1_MEMBERSHIP_REPORT 0x12 16 : #define IGMP_PROTO_DVMRP 0x13 17 : #define IGMP_PROTO_PIM 0x14 18 : #define IGMP_CISCO_TRACE 0x15 19 : #define IGMP_V2_MEMBERSHIP_REPORT 0x16 20 : #define IGMP_GROUP_LEAVE 0x17 21 : #define IGMP_MTRACE_RESPONSE 0x1e 22 : #define IGMP_MTRACE_REQUEST 0x1f 23 : #define IGMP_DWR 0x21 24 : #define IGMP_V3_MEMBERSHIP_REPORT 0x22 25 : #define IGMP_MAX_TYPE IGMP_V3_MEMBERSHIP_REPORT 26 : #define IGMP_MIN_PACKET_LENGTH 8 27 : 28 : #define IGMP_PKT_TRACE(obj, arg) \ 29 : do { \ 30 : std::ostringstream _str; \ 31 : _str << arg; \ 32 : Igmp##obj::TraceMsg(IgmpTraceBuf, __FILE__, __LINE__, _str.str()); \ 33 : } while (false) \ 34 : 35 : class Timer; 36 : class Interface; 37 : 38 : namespace IgmpInfo { 39 : struct IgmpItfStats { 40 218 : IgmpItfStats() { Reset(); } 41 286 : void Reset() { 42 286 : rx_unknown = 0; 43 286 : memset(rx_badpacket, 0x00, sizeof(uint32_t)*IGMP_MAX_TYPE); 44 286 : memset(rx_okpacket, 0x00, sizeof(uint32_t)*IGMP_MAX_TYPE); 45 286 : tx_packet = 0; 46 286 : tx_drop_packet = 0; 47 286 : } 48 : uint32_t rx_unknown; 49 : uint32_t rx_badpacket[IGMP_MAX_TYPE]; 50 : uint32_t rx_okpacket[IGMP_MAX_TYPE]; 51 : uint32_t tx_packet; 52 : uint32_t tx_drop_packet; 53 : }; 54 : 55 : struct IgmpSubnetState { 56 : public: 57 3 : IgmpSubnetState() { 58 3 : } 59 6 : virtual ~IgmpSubnetState() {} 60 : 61 0 : void IncrRxUnknown() { 62 0 : stats_.rx_unknown++; 63 0 : } 64 : uint32_t GetRxUnknown() { 65 : return stats_.rx_unknown; 66 : } 67 0 : void IncrRxBadPkt(unsigned long index) { 68 0 : stats_.rx_badpacket[index-1]++; 69 0 : } 70 : uint32_t GetRxBadPkt(unsigned long index) { 71 : return stats_.rx_badpacket[index-1]; 72 : } 73 0 : void IncrRxOkPkt(unsigned long index) { 74 0 : stats_.rx_okpacket[index-1]++; 75 0 : } 76 : uint32_t GetRxOkPkt(unsigned long index) { 77 : return stats_.rx_okpacket[index-1]; 78 : } 79 0 : void IncrTxPkt() { 80 0 : stats_.tx_packet++; 81 0 : } 82 : uint32_t GetTxPkt() { 83 : return stats_.tx_packet; 84 : } 85 0 : void IncrTxDropPkt() { 86 0 : stats_.tx_drop_packet++; 87 0 : } 88 : uint32_t GetTxDropPkt() { 89 : return stats_.tx_drop_packet; 90 : } 91 : 92 0 : const IgmpInfo::IgmpItfStats &GetItfStats() const { return stats_; } 93 0 : void ClearItfStats() { stats_.Reset(); } 94 : 95 : IgmpInfo::IgmpItfStats stats_; 96 : }; 97 : 98 : struct VnIgmpDBState : public DBState { 99 : public: 100 3 : VnIgmpDBState() : DBState() { 101 3 : } 102 6 : ~VnIgmpDBState() {} 103 : 104 : typedef std::map<IpAddress, IgmpSubnetState*> IgmpSubnetStateMap; 105 : IgmpSubnetStateMap igmp_state_map_; 106 : }; 107 : 108 : struct VmiIgmpDBState : public DBState { 109 : VmiIgmpDBState() : DBState(), vrf_name_() { 110 : } 111 : ~VmiIgmpDBState() {} 112 : 113 : std::string vrf_name_; 114 : }; 115 : } 116 : 117 : class IgmpProto : public Proto { 118 : public: 119 : 120 : struct IgmpStats { 121 7 : IgmpStats() { Reset(); } 122 57 : void Reset() { 123 57 : bad_length = bad_cksum = bad_interface = not_local = 124 57 : rx_unknown = rejected_pkt = ip_pkt_len = 0; 125 57 : } 126 : 127 : uint32_t bad_length; 128 : uint32_t bad_cksum; 129 : uint32_t bad_interface; 130 : uint32_t not_local; 131 : uint32_t rx_unknown; 132 : uint32_t rejected_pkt; 133 : uint32_t ip_pkt_len; 134 : }; 135 : 136 : void Shutdown(); 137 : IgmpProto(Agent *agent, boost::asio::io_context &io); 138 : virtual ~IgmpProto(); 139 : ProtoHandler *AllocProtoHandler(boost::shared_ptr<PktInfo> info, 140 : boost::asio::io_context &io); 141 : 142 : void IgmpProtoInit(void); 143 : 144 0 : void IncrStatsBadLength() { stats_.bad_length++; } 145 0 : void IncrStatsBadCksum() { stats_.bad_cksum++; } 146 0 : void IncrStatsBadInterface() { stats_.bad_interface++; } 147 : void IncrStatsNotLocal() { stats_.not_local++; } 148 0 : void IncrStatsRxUnknown() { stats_.rx_unknown++; } 149 0 : void IncrStatsRejectedPkt() { stats_.rejected_pkt++; } 150 0 : void IncrStatsIpPktLen() { stats_.ip_pkt_len++; } 151 5 : const IgmpStats &GetStats() const { return stats_; } 152 46 : void ClearStats() { stats_.Reset(); } 153 310 : GmpProto *GetGmpProto() { return gmp_proto_; } 154 : bool SendIgmpPacket(const VrfEntry *vrf, IpAddress gmp_addr, GmpPacket *packet); 155 : const bool GetItfStats(const VnEntry *vn, IpAddress gateway, 156 : IgmpInfo::IgmpItfStats &stats); 157 : void ClearItfStats(const VnEntry *vn, IpAddress gateway); 158 : void IncrSendStats(const VmInterface *vm_itf, bool tx_done); 159 : 160 : DBTableBase::ListenerId vn_listener_id (); 161 : 162 : private: 163 : void VnNotify(DBTablePartBase *part, DBEntryBase *entry); 164 : void Inet4McRouteTableNotify(DBTablePartBase *part, DBEntryBase *entry); 165 : 166 : void AsyncRead(); 167 : void ReadHandler(const boost::system::error_code &error, std::size_t len); 168 : 169 : const std::string task_name_; 170 : boost::asio::io_context &io_; 171 : 172 : DBTableBase::ListenerId vn_listener_id_; 173 : 174 : GmpProto *gmp_proto_; 175 : IgmpStats stats_; 176 : 177 : DISALLOW_COPY_AND_ASSIGN(IgmpProto); 178 : }; 179 : 180 : #endif // vnsw_agent_igmp_proto_hpp