22
22
}
23
23
)
24
24
25
+ const (
26
+ ignoreNonActiveInterfaceModulusCst = 100
27
+ )
28
+
25
29
func (r IGMPReporter ) recvIGMP (wg * sync.WaitGroup , ctx context.Context , interf side , g destIP ) {
26
30
27
31
defer wg .Done ()
@@ -69,9 +73,11 @@ forLoop:
69
73
// Ignore traffic on the non-active outside interface
70
74
if r .AltOutExists {
71
75
if r .ignoreOnNonActiveOutOrAltInterface (& interf ) {
72
- debugLog (r .debugLevel > 10 ,
73
- fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d ignoring on non active outside interface" ,
74
- interf , r .mapIPtoNetAddr [g ], loops ))
76
+ if loops % ignoreNonActiveInterfaceModulusCst == 0 {
77
+ debugLog (r .debugLevel > 10 ,
78
+ fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d ignoring on non active outside interface" ,
79
+ interf , r .mapIPtoNetAddr [g ], loops ))
80
+ }
75
81
76
82
bytePool .Put (buf )
77
83
continue
@@ -127,40 +133,45 @@ forLoop:
127
133
//------------------
128
134
// Validate this is IGMP and it's the correct type of IGMP
129
135
130
- // https://pkg.go.dev/github.com/tsg/gopacket#hdr-Basic_Usage
131
- // https://github.com/randomizedcoder/gopacket/blob/master/layers/igmp.go#L224
132
- packet := gopacket .NewPacket (* buf , layers .LayerTypeIGMP , gopacket .Default )
136
+ // type IGMPType uint8
133
137
134
- igmpLayer := packet .Layer (layers .LayerTypeIGMP )
135
- if igmpLayer == nil {
136
- debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d This isn't deserializing to IGMP. Ignoring" , interf , r .mapIPtoNetAddr [g ], loops ))
137
- r .pCrecvIGMP .WithLabelValues ("deserializing" , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
138
- bytePool .Put (buf )
139
- continue
140
- }
138
+ // const (
139
+ // IGMPMembershipQuery IGMPType = 0x11 // General or group specific query
140
+ // IGMPMembershipReportV1 IGMPType = 0x12 // Version 1 Membership Report
141
+ // IGMPMembershipReportV2 IGMPType = 0x16 // Version 2 Membership Report
142
+ // IGMPLeaveGroup IGMPType = 0x17 // Leave Group
143
+ // IGMPMembershipReportV3 IGMPType = 0x22 // Version 3 Membership Report
144
+ // )
145
+ // https://github.com/randomizedcoder/gopacket/blob/master/layers/igmp.go#L18C1-L27C2
141
146
142
- igmp , ok := igmpLayer .(* layers.IGMP )
147
+ igmpType := layers .IGMPType ((* buf )[0 ])
148
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d type:%s" , interf , r .mapIPtoNetAddr [g ], loops , igmpType ))
149
+ r .pC .WithLabelValues ("recvIGMP" , igmpType .String (), "count" ).Inc ()
150
+
151
+ _ , ok := r.mapIPtoIGMPType [g ][igmpType ]
143
152
if ! ok {
144
- debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d type cast error igmpLayer.(*layers.IGMP) " , interf , r .mapIPtoNetAddr [g ], loops ))
145
- r .pCrecvIGMP .WithLabelValues ("typeCast " , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
153
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d Packet is not of a valid IGMP type for this group. Ignoring " , interf , r .mapIPtoNetAddr [g ], loops ))
154
+ r .pCrecvIGMP .WithLabelValues ("igmpT " , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
146
155
bytePool .Put (buf )
147
156
continue
148
157
}
149
158
150
- //debugLog(r.debugLevel > 10, fmt.Sprint(igmp.Type))
159
+ // https://pkg.go.dev/github.com/tsg/gopacket#hdr-Basic_Usage
160
+ // https://github.com/randomizedcoder/gopacket/blob/master/layers/igmp.go#L224
161
+ packet := gopacket .NewPacket (* buf , layers .LayerTypeIGMP , gopacket .Default )
151
162
152
- igmpT , ok := r. mapIPtoIGMPType [ g ][igmp. Type ]
153
- if ! ok {
154
- debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d Packet is not of a valid IGMP type for this group. Ignoring" , interf , r .mapIPtoNetAddr [g ], loops ))
155
- r .pCrecvIGMP .WithLabelValues ("igmpT " , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
163
+ igmpLayer := packet . Layer ( layers . LayerTypeIGMP )
164
+ if igmpLayer == nil {
165
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d This isn't deserializing to IGMP. Ignoring" , interf , r .mapIPtoNetAddr [g ], loops ))
166
+ r .pCrecvIGMP .WithLabelValues ("deserializing " , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
156
167
bytePool .Put (buf )
157
168
continue
158
169
}
159
170
160
- switch igmpT {
171
+ switch igmpType {
161
172
162
- case igmpTypeQuery :
163
- r .pCrecvIGMP .WithLabelValues ("igmpTypeQuery " , interf .String (), r .mapIPtoNetAddr [g ].String (), "counter" ).Inc ()
173
+ case layers . IGMPMembershipQuery :
174
+ r .pCrecvIGMP .WithLabelValues ("IGMPMembershipQuery " , interf .String (), r .mapIPtoNetAddr [g ].String (), "counter" ).Inc ()
164
175
165
176
srcIP , err := r .netip2Addr (cm .Src )
166
177
if err != nil {
@@ -178,10 +189,46 @@ forLoop:
178
189
debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d QueryNotifyCh failed. Channel full? Is something reading from the channel?" , interf , r .mapIPtoNetAddr [g ], loops ))
179
190
}
180
191
}
181
- case igmpTypeMembershipReport :
182
- r .pCrecvIGMP .WithLabelValues ("igmpTypeMembershipReport" , interf .String (), r .mapIPtoNetAddr [g ].String (), "counter" ).Inc ()
183
192
184
- mitems := r .groupRecordsToMembershipItem (igmp .GroupRecords )
193
+ case layers .IGMPMembershipReportV2 :
194
+ r .pCrecvIGMP .WithLabelValues ("IGMPMembershipReportV2" , interf .String (), r .mapIPtoNetAddr [g ].String (), "counter" ).Inc ()
195
+
196
+ igmpv1or2 , okC := igmpLayer .(* layers.IGMPv1or2 )
197
+ if ! okC {
198
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d type cast error igmpLayer.(*layers.IGMPv1or2)" , interf , r .mapIPtoNetAddr [g ], loops ))
199
+ r .pC .WithLabelValues ("recvIGMP" , "cast" , "error" ).Inc ()
200
+ }
201
+
202
+ na , err := r .netip2Addr (igmpv1or2 .GroupAddress )
203
+ if err != nil {
204
+ log .Fatal ("recvIGMP netip2Addr(sa) err" , err )
205
+ }
206
+
207
+ var mi MembershipItem
208
+ mi .Group = na
209
+ mitems := []MembershipItem {mi }
210
+
211
+ if r .conf .MembershipReportsFromNetwork {
212
+ select {
213
+ case r .MembershipReportFromNetworkCh <- mitems :
214
+ r .pCrecvIGMP .WithLabelValues ("MembershipReportFromNetworkCh" , interf .String (), r .mapIPtoNetAddr [g ].String (), "counter" ).Inc ()
215
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d MembershipReportFromNetworkCh" , interf , r .mapIPtoNetAddr [g ], loops ))
216
+ default :
217
+ r .pCrecvIGMP .WithLabelValues ("MembershipReportFromNetworkCh" , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
218
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d MembershipReportFromNetworkCh failed. Channel full? Is something reading from the channel?" , interf , r .mapIPtoNetAddr [g ], loops ))
219
+ }
220
+ }
221
+ case layers .IGMPMembershipReportV3 :
222
+
223
+ igmp , ok := igmpLayer .(* layers.IGMP )
224
+ if ! ok {
225
+ debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d type cast error igmpLayer.(*layers.IGMP)" , interf , r .mapIPtoNetAddr [g ], loops ))
226
+ r .pCrecvIGMP .WithLabelValues ("typeCast" , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
227
+ bytePool .Put (buf )
228
+ continue
229
+ }
230
+
231
+ mitems := r .IGMPv3GroupRecordsToMembershipItem (igmp .GroupRecords )
185
232
186
233
if r .conf .MembershipReportsFromNetwork {
187
234
select {
@@ -193,6 +240,8 @@ forLoop:
193
240
debugLog (r .debugLevel > 10 , fmt .Sprintf ("recvIGMP(%s) g:%s loops:%d MembershipReportFromNetworkCh failed. Channel full? Is something reading from the channel?" , interf , r .mapIPtoNetAddr [g ], loops ))
194
241
}
195
242
}
243
+ //case layers.IGMPLeaveGroup:
244
+ // TODO handle leave
196
245
197
246
default :
198
247
r .pCrecvIGMP .WithLabelValues ("WrongType" , interf .String (), r .mapIPtoNetAddr [g ].String (), "error" ).Inc ()
@@ -258,17 +307,17 @@ func (r IGMPReporter) ignoreOnNonActiveOutOrAltInterface(interf *side) (ignore b
258
307
return ignore
259
308
}
260
309
261
- // groupRecordsToMembershipItem converts the real IGMP packet group memberships
310
+ // IGMPv3GroupRecordsToMembershipItem converts the real IGMP packet group memberships
262
311
// into the internal representatino as a list of []membershipItem
263
- func (r IGMPReporter ) groupRecordsToMembershipItem (groupRecords []layers.IGMPv3GroupRecord ) (mitems []MembershipItem ) {
312
+ func (r IGMPReporter ) IGMPv3GroupRecordsToMembershipItem (groupRecords []layers.IGMPv3GroupRecord ) (mitems []MembershipItem ) {
264
313
265
314
startTime := time .Now ()
266
315
defer func () {
267
- r .pH .WithLabelValues ("groupRecordsToMembershipItem " , "start" , "complete" ).Observe (time .Since (startTime ).Seconds ())
316
+ r .pH .WithLabelValues ("IGMPv3GroupRecordsToMembershipItem " , "start" , "complete" ).Observe (time .Since (startTime ).Seconds ())
268
317
}()
269
- r .pC .WithLabelValues ("groupRecordsToMembershipItem " , "start" , "count" ).Inc ()
318
+ r .pC .WithLabelValues ("IGMPv3GroupRecordsToMembershipItem " , "start" , "count" ).Inc ()
270
319
271
- debugLog (r .debugLevel > 100 , "groupRecordsToMembershipItem ()" )
320
+ debugLog (r .debugLevel > 100 , "IGMPv3GroupRecordsToMembershipItem ()" )
272
321
273
322
for _ , gr := range groupRecords {
274
323
var g MembershipItem
0 commit comments