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