[VOL-2778] Handling IGMP
Change-Id: I54c26bc438a144c7d4c64a9b3d543461fc743ab2
diff --git a/internal/bbsim/responders/igmp/igmp.go b/internal/bbsim/responders/igmp/igmp.go
index defbe19..5390347 100644
--- a/internal/bbsim/responders/igmp/igmp.go
+++ b/internal/bbsim/responders/igmp/igmp.go
@@ -15,25 +15,28 @@
import (
"encoding/binary"
+ "encoding/hex"
+ "errors"
+ "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
"net"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
bbsim "github.com/opencord/bbsim/internal/bbsim/types"
- omci "github.com/opencord/omci-sim"
- "github.com/opencord/voltha-protos/v2/go/openolt"
+ "github.com/opencord/voltha-protos/v3/go/openolt"
log "github.com/sirupsen/logrus"
)
-func SendIGMPLeaveGroupV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, macAddress net.HardwareAddr, stream bbsim.Stream) error {
+func SendIGMPLeaveGroupV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+ gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream) error {
log.WithFields(log.Fields{
"OnuId": onuId,
"SerialNumber": serialNumber,
"PortNo": portNo,
}).Debugf("Entered SendIGMPLeaveGroupV2")
igmp := createIGMPV2LeaveRequestPacket()
- pkt, err := serializeIgmpPacket(ponPortId, onuId, macAddress, igmp)
+ pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
if err != nil {
log.WithFields(log.Fields{
@@ -44,21 +47,11 @@
return err
}
- gemid, err := omci.GetGemPortId(ponPortId, onuId)
- if err != nil {
- log.WithFields(log.Fields{
- "OnuId": onuId,
- "IntfId": ponPortId,
- "SerialNumber": serialNumber,
- }).Errorf("Can't retrieve GemPortId for IGMP: %s", err)
- return err
- }
-
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
IntfId: ponPortId,
- GemportId: uint32(gemid),
+ GemportId: gemPortId,
Pkt: pkt,
PortNo: portNo,
},
@@ -77,14 +70,11 @@
return nil
}
-func SendIGMPMembershipReportV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, macAddress net.HardwareAddr, stream bbsim.Stream) error {
- log.WithFields(log.Fields{
- "OnuId": onuId,
- "SerialNumber": serialNumber,
- "PortNo": portNo,
- }).Debugf("Entered SendIGMPMembershipReportV2")
+func SendIGMPMembershipReportV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+ gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream) error {
+
igmp := createIGMPV2MembershipReportPacket()
- pkt, err := serializeIgmpPacket(ponPortId, onuId, macAddress, igmp)
+ pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
if err != nil {
log.WithFields(log.Fields{
@@ -95,21 +85,11 @@
return err
}
- gemid, err := omci.GetGemPortId(ponPortId, onuId)
- if err != nil {
- log.WithFields(log.Fields{
- "OnuId": onuId,
- "IntfId": ponPortId,
- "SerialNumber": serialNumber,
- }).Errorf("Can't retrieve GemPortId for IGMP: %s", err)
- return err
- }
-
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
IntfId: ponPortId,
- GemportId: uint32(gemid),
+ GemportId: gemPortId,
Pkt: pkt,
PortNo: portNo,
},
@@ -125,17 +105,24 @@
}).Errorf("Fail to send IGMP PktInd indication")
return err
}
+
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "SerialNumber": serialNumber,
+ "PortNo": portNo,
+ }).Debugf("Sent SendIGMPMembershipReportV2")
return nil
}
-func SendIGMPMembershipReportV3(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, macAddress net.HardwareAddr, stream bbsim.Stream) error {
+func SendIGMPMembershipReportV3(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+ gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream) error {
log.WithFields(log.Fields{
"OnuId": onuId,
"SerialNumber": serialNumber,
"PortNo": portNo,
}).Debugf("Entered SendIGMPMembershipReportV3")
igmp := createIGMPV3MembershipReportPacket()
- pkt, err := serializeIgmpPacket(ponPortId, onuId, macAddress, igmp)
+ pkt, err := serializeIgmpPacket(ponPortId, onuId, cTag, macAddress, pbit, igmp)
if err != nil {
log.WithFields(log.Fields{
@@ -146,21 +133,11 @@
return err
}
- gemid, err := omci.GetGemPortId(ponPortId, onuId)
- if err != nil {
- log.WithFields(log.Fields{
- "OnuId": onuId,
- "IntfId": ponPortId,
- "SerialNumber": serialNumber,
- }).Errorf("Can't retrieve GemPortId for IGMP: %s", err)
- return err
- }
-
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
IntfId: ponPortId,
- GemportId: uint32(gemid),
+ GemportId: gemPortId,
Pkt: pkt,
PortNo: portNo,
},
@@ -178,7 +155,34 @@
return nil
}
-func createIGMPV3MembershipReportPacket() IGMP {
+func HandleNextPacket(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+ gemPortId uint32, macAddress net.HardwareAddr, pkt gopacket.Packet, cTag int, pbit uint8, stream bbsim.Stream) error {
+
+ igmpLayer := pkt.Layer(layers.LayerTypeIGMP)
+ if igmpLayer == nil {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "SerialNumber": serialNumber,
+ "PortNo": portNo,
+ "Pkt": hex.EncodeToString(pkt.Data()),
+ }).Error("This is not an IGMP packet")
+ return errors.New("packet-is-not-igmp")
+ }
+
+ log.WithFields(log.Fields{
+ "Pkt": pkt.Data(),
+ }).Trace("IGMP packet")
+
+ igmp := igmpLayer.(*layers.IGMPv1or2)
+
+ if igmp.Type == layers.IGMPMembershipQuery {
+ _ = SendIGMPMembershipReportV2(ponPortId, onuId, serialNumber, portNo, gemPortId, macAddress, cTag, pbit, stream)
+ }
+
+ return nil
+}
+
+func createIGMPV3MembershipReportPacket() *IGMP {
groupRecord1 := IGMPv3GroupRecord{
Type: IGMPv3GroupRecordType(IGMPIsIn),
@@ -198,8 +202,8 @@
AuxData: 0, // NOT USED
}
- igmpDefault := IGMP{
- Type: 0x22, //IGMPV3 Membership Report
+ igmpDefault := &IGMP{
+ Type: layers.IGMPMembershipReportV3, //IGMPV3 Membership Report
MaxResponseTime: time.Duration(1),
Checksum: 0,
GroupAddress: net.IPv4(224, 0, 0, 22),
@@ -216,10 +220,18 @@
return igmpDefault
}
-//func serializeIgmpPacket(intfId uint32, onuId uint32, srcMac net.HardwareAddr, igmp *layers.IGMP) ([]byte, error) {
-func createIGMPV2MembershipReportPacket() IGMP {
- return IGMP{
- Type: 0x16, //IGMPV2 Membership Report
+func createIGMPV2MembershipReportPacket() *IGMP {
+ return &IGMP{
+ Type: layers.IGMPMembershipReportV2, //IGMPV2 Membership Report
+ Checksum: 0,
+ GroupAddress: net.IPv4(224, 0, 0, 22),
+ Version: 2,
+ }
+}
+
+func createIGMPV2LeaveRequestPacket() *IGMP {
+ return &IGMP{
+ Type: layers.IGMPLeaveGroup, //IGMPV2 Leave Group
MaxResponseTime: time.Duration(1),
Checksum: 0,
GroupAddress: net.IPv4(224, 0, 0, 22),
@@ -227,17 +239,7 @@
}
}
-func createIGMPV2LeaveRequestPacket() IGMP {
- return IGMP{
- Type: 0x17, //IGMPV2 Leave Group
- MaxResponseTime: time.Duration(1),
- Checksum: 0,
- GroupAddress: net.IPv4(224, 0, 0, 22),
- Version: 2,
- }
-}
-
-func serializeIgmpPacket(intfId uint32, onuId uint32, srcMac net.HardwareAddr, igmp IGMP) ([]byte, error) {
+func serializeIgmpPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, pbit uint8, igmp *IGMP) ([]byte, error) {
buffer := gopacket.NewSerializeBuffer()
options := gopacket.SerializeOptions{
ComputeChecksums: true,
@@ -265,28 +267,22 @@
return nil, err
}
- return buffer.Bytes(), nil
+ untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
+ taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt, pbit)
+
+ if err != nil {
+ log.Error("TagPacket")
+ return nil, err
+ }
+
+ return taggedPkt.Data(), nil
}
//-----------------------------------------***********************---------------------------------
-// BaseLayer is a convenience struct which implements the LayerData and
-// LayerPayload functions of the Layer interface.
-type BaseLayer struct {
- // Contents is the set of bytes that make up this layer. IE: for an
- // Ethernet packet, this would be the set of bytes making up the
- // Ethernet frame.
- Contents []byte
- // Payload is the set of bytes contained by (but not part of) this
- // Layer. Again, to take Ethernet as an example, this would be the
- // set of bytes encapsulated by the Ethernet protocol.
- Payload []byte
-}
-
-type IGMPType uint8
type IGMP struct {
- BaseLayer
- Type IGMPType
+ layers.BaseLayer
+ Type layers.IGMPType
MaxResponseTime time.Duration
Checksum uint16
GroupAddress net.IP
@@ -343,8 +339,7 @@
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
-func (igmp IGMP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- log.Debugf("Serializing IGMP Packet")
+func (igmp *IGMP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
data, err := b.PrependBytes(8915)
if err != nil {
return err
@@ -410,4 +405,6 @@
return ^uint16(csum)
}
-func (IGMP) LayerType() gopacket.LayerType { return layers.LayerTypeIGMP }
+func (i *IGMP) LayerType() gopacket.LayerType { return layers.LayerTypeIGMP }
+func (i *IGMP) LayerContents() []byte { return i.Contents }
+func (i *IGMP) LayerPayload() []byte { return i.Payload }