blob: 4dd007b42dde09e7b6e3399f7bc1afa35a1bba49 [file] [log] [blame]
Arjun E K57a7fcb2020-01-30 06:44:45 +00001/*
2 * Copyright 2018-present Open Networking Foundation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 */
13
14package igmp
15
16import (
17 "encoding/binary"
Matteo Scandolo618a6582020-09-09 12:21:29 -070018 "encoding/hex"
19 "errors"
20 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Anand S Katti09541352020-01-29 15:54:01 +053021 "net"
22 "time"
23
Arjun E K57a7fcb2020-01-30 06:44:45 +000024 "github.com/google/gopacket"
25 "github.com/google/gopacket/layers"
26 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000027 "github.com/opencord/voltha-protos/v5/go/openolt"
Arjun E K57a7fcb2020-01-30 06:44:45 +000028 log "github.com/sirupsen/logrus"
Arjun E K57a7fcb2020-01-30 06:44:45 +000029)
30
Matteo Scandolo618a6582020-09-09 12:21:29 -070031func SendIGMPLeaveGroupV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000032 gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
Arjun E K57a7fcb2020-01-30 06:44:45 +000033 log.WithFields(log.Fields{
34 "OnuId": onuId,
35 "SerialNumber": serialNumber,
36 "PortNo": portNo,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000037 "GroupAddress": groupAddress,
Arjun E K57a7fcb2020-01-30 06:44:45 +000038 }).Debugf("Entered SendIGMPLeaveGroupV2")
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000039 igmp := createIGMPV2LeaveRequestPacket(groupAddress)
Matteo Scandolo618a6582020-09-09 12:21:29 -070040 pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
Arjun E K57a7fcb2020-01-30 06:44:45 +000041
42 if err != nil {
43 log.WithFields(log.Fields{
44 "OnuId": onuId,
45 "IntfId": ponPortId,
46 "SerialNumber": serialNumber,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000047 "GroupAddress": groupAddress,
Arjun E K57a7fcb2020-01-30 06:44:45 +000048 }).Errorf("Seriliazation of igmp packet failed : %s", err)
49 return err
50 }
51
Arjun E K57a7fcb2020-01-30 06:44:45 +000052 data := &openolt.Indication_PktInd{
53 PktInd: &openolt.PacketIndication{
54 IntfType: "pon",
55 IntfId: ponPortId,
Matteo Scandolo618a6582020-09-09 12:21:29 -070056 GemportId: gemPortId,
Arjun E K57a7fcb2020-01-30 06:44:45 +000057 Pkt: pkt,
58 PortNo: portNo,
Girish Gowdra62f24292021-05-12 16:28:39 -070059 OnuId: onuId,
60 UniId: 0, // FIXME: When multi-uni support comes in, this hardcoding has to be removed
Arjun E K57a7fcb2020-01-30 06:44:45 +000061 },
62 }
63 //Sending IGMP packets
64 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo583f17d2020-02-13 10:35:17 -080065 log.WithFields(log.Fields{
66 "OnuId": onuId,
67 "SerialNumber": serialNumber,
68 "PortNo": portNo,
69 "IntfId": ponPortId,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000070 "GroupAddress": groupAddress,
Matteo Scandolo583f17d2020-02-13 10:35:17 -080071 "err": err,
72 }).Error("Fail to send IGMP PktInd indication for ONU")
Arjun E K57a7fcb2020-01-30 06:44:45 +000073 return err
74 }
75 return nil
76}
77
Matteo Scandolo618a6582020-09-09 12:21:29 -070078func SendIGMPMembershipReportV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000079 gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
Matteo Scandolo618a6582020-09-09 12:21:29 -070080
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000081 igmp := createIGMPV2MembershipReportPacket(groupAddress)
Matteo Scandolo618a6582020-09-09 12:21:29 -070082 pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
Arjun E K57a7fcb2020-01-30 06:44:45 +000083
84 if err != nil {
85 log.WithFields(log.Fields{
86 "OnuId": onuId,
87 "IntfId": ponPortId,
88 "SerialNumber": serialNumber,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +000089 "GroupAddress": groupAddress,
Arjun E K57a7fcb2020-01-30 06:44:45 +000090 }).Errorf("Seriliazation of igmp packet failed : %s", err)
91 return err
92 }
93
Arjun E K57a7fcb2020-01-30 06:44:45 +000094 data := &openolt.Indication_PktInd{
95 PktInd: &openolt.PacketIndication{
96 IntfType: "pon",
97 IntfId: ponPortId,
Matteo Scandolo618a6582020-09-09 12:21:29 -070098 GemportId: gemPortId,
Arjun E K57a7fcb2020-01-30 06:44:45 +000099 Pkt: pkt,
100 PortNo: portNo,
Girish Gowdra62f24292021-05-12 16:28:39 -0700101 OnuId: onuId,
102 UniId: 0,
Arjun E K57a7fcb2020-01-30 06:44:45 +0000103 },
104 }
105 //Sending IGMP packets
106 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo583f17d2020-02-13 10:35:17 -0800107 log.WithFields(log.Fields{
108 "OnuId": onuId,
109 "SerialNumber": serialNumber,
110 "PortNo": portNo,
111 "IntfId": ponPortId,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000112 "GroupAddress": groupAddress,
Matteo Scandolo583f17d2020-02-13 10:35:17 -0800113 "err": err,
114 }).Errorf("Fail to send IGMP PktInd indication")
Arjun E K57a7fcb2020-01-30 06:44:45 +0000115 return err
116 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700117
118 log.WithFields(log.Fields{
119 "OnuId": onuId,
120 "SerialNumber": serialNumber,
121 "PortNo": portNo,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000122 "GroupAddress": groupAddress,
Matteo Scandolo618a6582020-09-09 12:21:29 -0700123 }).Debugf("Sent SendIGMPMembershipReportV2")
Arjun E K57a7fcb2020-01-30 06:44:45 +0000124 return nil
125}
126
Matteo Scandolo618a6582020-09-09 12:21:29 -0700127func SendIGMPMembershipReportV3(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000128 gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
129
Anand S Katti09541352020-01-29 15:54:01 +0530130 log.WithFields(log.Fields{
131 "OnuId": onuId,
132 "SerialNumber": serialNumber,
133 "PortNo": portNo,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000134 "GroupAddress": groupAddress,
Anand S Katti09541352020-01-29 15:54:01 +0530135 }).Debugf("Entered SendIGMPMembershipReportV3")
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000136 igmp := createIGMPV3MembershipReportPacket(groupAddress)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700137 pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
Arjun E Kdd443f02020-02-07 15:24:01 +0000138
Anand S Katti09541352020-01-29 15:54:01 +0530139 if err != nil {
140 log.WithFields(log.Fields{
141 "OnuId": onuId,
142 "IntfId": ponPortId,
143 "SerialNumber": serialNumber,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000144 "GroupAddress": groupAddress,
Anand S Katti09541352020-01-29 15:54:01 +0530145 }).Errorf("Seriliazation of igmp packet failed : %s", err)
146 return err
147 }
Arjun E Kdd443f02020-02-07 15:24:01 +0000148
Anand S Katti09541352020-01-29 15:54:01 +0530149 data := &openolt.Indication_PktInd{
150 PktInd: &openolt.PacketIndication{
151 IntfType: "pon",
152 IntfId: ponPortId,
Matteo Scandolo618a6582020-09-09 12:21:29 -0700153 GemportId: gemPortId,
Anand S Katti09541352020-01-29 15:54:01 +0530154 Pkt: pkt,
155 PortNo: portNo,
Girish Gowdra62f24292021-05-12 16:28:39 -0700156 OnuId: onuId,
157 UniId: 0, // FIXME: When multi-uni support comes in, this hardcoding has to be removed
Anand S Katti09541352020-01-29 15:54:01 +0530158 },
159 }
160 //Sending IGMP packets
161 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo446fc9e2020-03-13 15:48:13 -0700162 log.WithFields(log.Fields{
163 "OnuId": onuId,
164 "IntfId": ponPortId,
165 "SerialNumber": serialNumber,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000166 "GroupAddress": groupAddress,
Matteo Scandolo446fc9e2020-03-13 15:48:13 -0700167 "err": err,
168 }).Errorf("Fail to send IGMP PktInd indication")
Anand S Katti09541352020-01-29 15:54:01 +0530169 return err
170 }
171 return nil
Arjun E Kdd443f02020-02-07 15:24:01 +0000172}
173
Matteo Scandolo618a6582020-09-09 12:21:29 -0700174func HandleNextPacket(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
175 gemPortId uint32, macAddress net.HardwareAddr, pkt gopacket.Packet, cTag int, pbit uint8, stream bbsim.Stream) error {
176
177 igmpLayer := pkt.Layer(layers.LayerTypeIGMP)
178 if igmpLayer == nil {
179 log.WithFields(log.Fields{
180 "OnuId": onuId,
181 "SerialNumber": serialNumber,
182 "PortNo": portNo,
183 "Pkt": hex.EncodeToString(pkt.Data()),
184 }).Error("This is not an IGMP packet")
185 return errors.New("packet-is-not-igmp")
186 }
187
188 log.WithFields(log.Fields{
189 "Pkt": pkt.Data(),
190 }).Trace("IGMP packet")
191
192 igmp := igmpLayer.(*layers.IGMPv1or2)
193
194 if igmp.Type == layers.IGMPMembershipQuery {
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000195 _ = SendIGMPMembershipReportV2(ponPortId, onuId, serialNumber, portNo, gemPortId, macAddress,
196 cTag, pbit, stream, igmp.GroupAddress.String())
Matteo Scandolo618a6582020-09-09 12:21:29 -0700197 }
198
199 return nil
200}
201
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000202func createIGMPV3MembershipReportPacket(groupAddress string) *IGMP {
Arjun E Kdd443f02020-02-07 15:24:01 +0000203
Anand S Katti09541352020-01-29 15:54:01 +0530204 groupRecord1 := IGMPv3GroupRecord{
205 Type: IGMPv3GroupRecordType(IGMPIsIn),
206 AuxDataLen: 0, // this should always be 0 as per IGMPv3 spec.
207 NumberOfSources: 3,
208 MulticastAddress: net.IPv4(224, 0, 0, 22),
209 SourceAddresses: []net.IP{net.IPv4(15, 14, 20, 24), net.IPv4(15, 14, 20, 26), net.IPv4(15, 14, 20, 25)},
210 AuxData: 0, // NOT USED
211 }
Arjun E Kdd443f02020-02-07 15:24:01 +0000212
Anand S Katti09541352020-01-29 15:54:01 +0530213 groupRecord2 := IGMPv3GroupRecord{
214 Type: IGMPv3GroupRecordType(IGMPIsIn),
215 AuxDataLen: 0, // this should always be 0 as per IGMPv3 spec.
216 NumberOfSources: 2,
217 MulticastAddress: net.IPv4(224, 0, 0, 25),
218 SourceAddresses: []net.IP{net.IPv4(15, 14, 20, 30), net.IPv4(15, 14, 20, 31)},
219 AuxData: 0, // NOT USED
220 }
Arjun E Kdd443f02020-02-07 15:24:01 +0000221
Matteo Scandolo618a6582020-09-09 12:21:29 -0700222 igmpDefault := &IGMP{
223 Type: layers.IGMPMembershipReportV3, //IGMPV3 Membership Report
Anand S Katti09541352020-01-29 15:54:01 +0530224 MaxResponseTime: time.Duration(1),
225 Checksum: 0,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000226 GroupAddress: net.ParseIP(groupAddress),
Anand S Katti09541352020-01-29 15:54:01 +0530227 SupressRouterProcessing: false,
228 RobustnessValue: 0,
229 IntervalTime: time.Duration(1),
230 SourceAddresses: []net.IP{net.IPv4(224, 0, 0, 24)},
231 NumberOfGroupRecords: 2,
232 NumberOfSources: 1,
233 GroupRecords: []IGMPv3GroupRecord{groupRecord1, groupRecord2},
234 Version: 3,
235 }
Arjun E Kdd443f02020-02-07 15:24:01 +0000236
Anand S Katti09541352020-01-29 15:54:01 +0530237 return igmpDefault
Arjun E Kdd443f02020-02-07 15:24:01 +0000238}
239
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000240func createIGMPV2MembershipReportPacket(groupAddress string) *IGMP {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700241 return &IGMP{
242 Type: layers.IGMPMembershipReportV2, //IGMPV2 Membership Report
243 Checksum: 0,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000244 GroupAddress: net.ParseIP(groupAddress),
Matteo Scandolo618a6582020-09-09 12:21:29 -0700245 Version: 2,
246 }
247}
248
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000249func createIGMPV2LeaveRequestPacket(groupAddress string) *IGMP {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700250 return &IGMP{
251 Type: layers.IGMPLeaveGroup, //IGMPV2 Leave Group
Arjun E K57a7fcb2020-01-30 06:44:45 +0000252 MaxResponseTime: time.Duration(1),
253 Checksum: 0,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000254 GroupAddress: net.ParseIP(groupAddress),
Arjun E K57a7fcb2020-01-30 06:44:45 +0000255 Version: 2,
256 }
257}
258
Matteo Scandolo618a6582020-09-09 12:21:29 -0700259func serializeIgmpPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, pbit uint8, igmp *IGMP) ([]byte, error) {
Arjun E K57a7fcb2020-01-30 06:44:45 +0000260 buffer := gopacket.NewSerializeBuffer()
261 options := gopacket.SerializeOptions{
262 ComputeChecksums: true,
263 FixLengths: true,
264 }
265
266 ethernetLayer := &layers.Ethernet{
267 SrcMAC: srcMac,
268 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
269 EthernetType: layers.EthernetTypeIPv4,
270 }
271
272 ipLayer := &layers.IPv4{
273 Version: 4,
274 TOS: 0x10,
275 Id: 0,
276 TTL: 128,
277 SrcIP: []byte{0, 0, 0, 0},
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000278 DstIP: igmp.GroupAddress,
Arjun E K57a7fcb2020-01-30 06:44:45 +0000279 Protocol: layers.IPProtocolIGMP,
280 Options: []layers.IPv4Option{{OptionType: 148, OptionLength: 4, OptionData: make([]byte, 0)}}, //Adding router alert option
281 }
282
283 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, igmp); err != nil {
284 return nil, err
285 }
286
Matteo Scandolo618a6582020-09-09 12:21:29 -0700287 untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
288 taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt, pbit)
289
290 if err != nil {
291 log.Error("TagPacket")
292 return nil, err
293 }
294
295 return taggedPkt.Data(), nil
Arjun E K57a7fcb2020-01-30 06:44:45 +0000296}
297
298//-----------------------------------------***********************---------------------------------
Arjun E K57a7fcb2020-01-30 06:44:45 +0000299
300type IGMP struct {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700301 layers.BaseLayer
302 Type layers.IGMPType
Arjun E K57a7fcb2020-01-30 06:44:45 +0000303 MaxResponseTime time.Duration
304 Checksum uint16
305 GroupAddress net.IP
306 SupressRouterProcessing bool
307 RobustnessValue uint8
308 IntervalTime time.Duration
309 SourceAddresses []net.IP
310 NumberOfGroupRecords uint16
311 NumberOfSources uint16
Anand S Katti09541352020-01-29 15:54:01 +0530312 GroupRecords []IGMPv3GroupRecord
Arjun E K57a7fcb2020-01-30 06:44:45 +0000313 Version uint8 // IGMP protocol version
314}
315
Arjun E Kdd443f02020-02-07 15:24:01 +0000316// IGMPv3GroupRecord stores individual group records for a V3 Membership Report message.
317type IGMPv3GroupRecord struct {
Anand S Katti09541352020-01-29 15:54:01 +0530318 Type IGMPv3GroupRecordType
319 AuxDataLen uint8 // this should always be 0 as per IGMPv3 spec.
320 NumberOfSources uint16
321 MulticastAddress net.IP
322 SourceAddresses []net.IP
323 AuxData uint32 // NOT USED
Arjun E Kdd443f02020-02-07 15:24:01 +0000324}
325
326type IGMPv3GroupRecordType uint8
327
328const (
Anand S Katti09541352020-01-29 15:54:01 +0530329 IGMPIsIn IGMPv3GroupRecordType = 0x01 // Type MODE_IS_INCLUDE, source addresses x
330 IGMPIsEx IGMPv3GroupRecordType = 0x02 // Type MODE_IS_EXCLUDE, source addresses x
331 IGMPToIn IGMPv3GroupRecordType = 0x03 // Type CHANGE_TO_INCLUDE_MODE, source addresses x
332 IGMPToEx IGMPv3GroupRecordType = 0x04 // Type CHANGE_TO_EXCLUDE_MODE, source addresses x
333 IGMPAllow IGMPv3GroupRecordType = 0x05 // Type ALLOW_NEW_SOURCES, source addresses x
334 IGMPBlock IGMPv3GroupRecordType = 0x06 // Type BLOCK_OLD_SOURCES, source addresses x
Arjun E Kdd443f02020-02-07 15:24:01 +0000335)
336
337func (i IGMPv3GroupRecordType) String() string {
Anand S Katti09541352020-01-29 15:54:01 +0530338 switch i {
339 case IGMPIsIn:
340 return "MODE_IS_INCLUDE"
341 case IGMPIsEx:
342 return "MODE_IS_EXCLUDE"
343 case IGMPToIn:
344 return "CHANGE_TO_INCLUDE_MODE"
345 case IGMPToEx:
346 return "CHANGE_TO_EXCLUDE_MODE"
347 case IGMPAllow:
348 return "ALLOW_NEW_SOURCES"
349 case IGMPBlock:
350 return "BLOCK_OLD_SOURCES"
351 default:
352 return ""
353 }
Arjun E Kdd443f02020-02-07 15:24:01 +0000354}
355
Arjun E K57a7fcb2020-01-30 06:44:45 +0000356// SerializeTo writes the serialized form of this layer into the
357// SerializationBuffer, implementing gopacket.SerializableLayer.
358// See the docs for gopacket.SerializableLayer for more info.
Matteo Scandolo618a6582020-09-09 12:21:29 -0700359func (igmp *IGMP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
Arjun E K57a7fcb2020-01-30 06:44:45 +0000360 data, err := b.PrependBytes(8915)
Anand S Katti09541352020-01-29 15:54:01 +0530361 if err != nil {
362 return err
363 }
364 if igmp.Version == 2 {
365 data[0] = byte(igmp.Type)
366 data[1] = byte(igmp.MaxResponseTime)
367 data[2] = 0
368 data[3] = 0
369 copy(data[4:8], igmp.GroupAddress.To4())
370 if opts.ComputeChecksums {
371 igmp.Checksum = tcpipChecksum(data, 0)
372 binary.BigEndian.PutUint16(data[2:4], igmp.Checksum)
373 }
374 } else if igmp.Version == 3 {
Arjun E K57a7fcb2020-01-30 06:44:45 +0000375
Anand S Katti09541352020-01-29 15:54:01 +0530376 data[0] = byte(igmp.Type)
377 data[1] = 0
378 data[2] = 0
379 data[3] = 0
380 data[4] = 0
381 data[5] = 0
382 binary.BigEndian.PutUint16(data[6:8], igmp.NumberOfGroupRecords)
383 j := 8
384 for i := uint16(0); i < igmp.NumberOfGroupRecords; i++ {
385 data[j] = byte(igmp.GroupRecords[i].Type)
386 data[j+1] = byte(0)
387 binary.BigEndian.PutUint16(data[j+2:j+4], igmp.GroupRecords[i].NumberOfSources)
388 copy(data[j+4:j+8], igmp.GroupRecords[i].MulticastAddress.To4())
389 j = j + 8
390 for m := uint16(0); m < igmp.GroupRecords[i].NumberOfSources; m++ {
391 copy(data[j:(j+4)], igmp.GroupRecords[i].SourceAddresses[m].To4())
392 j = j + 4
393 }
394 }
395 if opts.ComputeChecksums {
396 igmp.Checksum = tcpipChecksum(data, 0)
397 binary.BigEndian.PutUint16(data[2:4], igmp.Checksum)
398 }
399 }
400 return nil
Arjun E K57a7fcb2020-01-30 06:44:45 +0000401}
402
403// Calculate the TCP/IP checksum defined in rfc1071. The passed-in csum is any
404// initial checksum data that's already been computed.
405func tcpipChecksum(data []byte, csum uint32) uint16 {
406 // to handle odd lengths, we loop to length - 1, incrementing by 2, then
407 // handle the last byte specifically by checking against the original
408 // length.
409 length := len(data) - 1
410 for i := 0; i < length; i += 2 {
411 // For our test packet, doing this manually is about 25% faster
412 // (740 ns vs. 1000ns) than doing it by calling binary.BigEndian.Uint16.
413 csum += uint32(data[i]) << 8
414 csum += uint32(data[i+1])
415 }
416 if len(data)%2 == 1 {
417 csum += uint32(data[length]) << 8
418 }
419 for csum > 0xffff {
420 csum = (csum >> 16) + (csum & 0xffff)
421 }
422 return ^uint16(csum)
423}
424
Matteo Scandolo618a6582020-09-09 12:21:29 -0700425func (i *IGMP) LayerType() gopacket.LayerType { return layers.LayerTypeIGMP }
426func (i *IGMP) LayerContents() []byte { return i.Contents }
427func (i *IGMP) LayerPayload() []byte { return i.Payload }