[VOL-4968] added mandatory uni-id optional vlan-id params, remove igmp event mechanism
Change-Id: Id103b8bb2d882b6b02ac483c44f57639fbd62ba1
diff --git a/internal/bbr/devices/olt.go b/internal/bbr/devices/olt.go
index 873a464..377ca50 100644
--- a/internal/bbr/devices/olt.go
+++ b/internal/bbr/devices/olt.go
@@ -20,7 +20,6 @@
"context"
"encoding/hex"
"fmt"
- "github.com/opencord/bbsim/internal/bbsim/types"
"io"
"reflect"
"time"
@@ -29,6 +28,7 @@
"github.com/google/gopacket/layers"
"github.com/opencord/bbsim/internal/bbsim/devices"
"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
+ "github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/bbsim/internal/common"
"github.com/opencord/voltha-protos/v5/go/openolt"
log "github.com/sirupsen/logrus"
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index 29c52ac..72d34ec 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -21,11 +21,11 @@
"fmt"
"strconv"
- "github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/voltha-protos/v5/go/openolt"
"github.com/opencord/bbsim/api/bbsim"
"github.com/opencord/bbsim/internal/bbsim/devices"
+ "github.com/opencord/bbsim/internal/bbsim/responders/igmp"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
)
@@ -236,19 +236,20 @@
res := &bbsim.Response{}
logger.WithFields(log.Fields{
- "OnuSn": req.OnuReq.SerialNumber,
+ "OnuSn": req.OnuSerialNumber,
+ "UniId": req.UniID,
"subAction": req.SubActionVal,
"GroupAddress": req.GroupAddress,
+ "VLAN": req.VLAN,
}).Info("Received igmp request for ONU")
olt := devices.GetOLT()
- onu, err := olt.FindOnuBySn(req.OnuReq.SerialNumber)
-
+ onu, err := olt.FindOnuBySn(req.OnuSerialNumber)
if err != nil {
res.StatusCode = int32(codes.NotFound)
res.Message = err.Error()
logger.WithFields(log.Fields{
- "OnuSn": req.OnuReq.SerialNumber,
+ "OnuSn": req.OnuSerialNumber,
"subAction": req.SubActionVal,
"GroupAddress": req.GroupAddress,
}).Warn("ONU not found for sending igmp packet.")
@@ -264,82 +265,74 @@
event = "igmp_join_startv3"
}
- errors := []string{}
- startedOn := []string{}
- success := true
-
- for _, u := range onu.UniPorts {
- uni := u.(*devices.UniPort)
- if !uni.OperState.Is(devices.UniStateUp) {
- // if the UNI is disabled, ignore it
- continue
- }
- for _, s := range uni.Services {
- service := s.(*devices.Service)
- serviceKey := fmt.Sprintf("uni[%d]%s", uni.ID, service.Name)
- if service.NeedsIgmp {
- if !service.InternalState.Is(devices.ServiceStateInitialized) {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "UniId": uni.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- "Service": service.Name,
- }).Warn("service-not-initialized-skipping-event")
- continue
- }
+ if int(req.UniID) >= len(onu.UniPorts) {
+ res.StatusCode = int32(codes.InvalidArgument)
+ err := fmt.Errorf("invalid uni no given")
+ return res, err
+ }
+ if req.VLAN > 0xFFF || req.VLAN < 0 {
+ res.StatusCode = int32(codes.InvalidArgument)
+ err := fmt.Errorf("invalid vlan given")
+ return res, err
+ }
+ uni := onu.UniPorts[req.UniID].(*devices.UniPort)
+ if !uni.OperState.Is(devices.UniStateUp) {
+ // if the UNI is disabled, ignore it
+ err := fmt.Errorf("given uni is currently disabled")
+ return res, err
+ }
+ for _, s := range uni.Services {
+ service := s.(*devices.Service)
+ if service.NeedsIgmp {
+ if !service.InternalState.Is(devices.ServiceStateInitialized) {
logger.WithFields(log.Fields{
"OnuId": onu.ID,
"UniId": uni.ID,
"IntfId": onu.PonPortID,
"OnuSn": onu.Sn(),
"Service": service.Name,
- "Uni": uni.ID,
- }).Debugf("Sending %s event on Service %s", event, service.Name)
+ }).Trace("service-not-initialized-skipping-event")
+ continue
+ }
- if err := service.IGMPState.Event(event, types.IgmpMessage{GroupAddress: req.GroupAddress}); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "UniId": uni.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- "Service": service.Name,
- }).Errorf("IGMP request failed: %s", err.Error())
- errors = append(errors, fmt.Sprintf("%s: %s", serviceKey, err.Error()))
- success = false
- }
- startedOn = append(startedOn, serviceKey)
+ ctag := service.CTag
+ if req.VLAN != 0 {
+ ctag = int(req.VLAN)
+ }
+
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "UniId": uni.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ "Service": service.Name,
+ "Uni": uni.ID,
+ "Vlan": ctag,
+ }).Debugf("Sending %s event on Service %s", event, service.Name)
+
+ switch req.SubActionVal {
+ case bbsim.SubActionTypes_JOIN:
+ go func() {
+ _ = igmp.SendIGMPMembershipReportV2(service.UniPort.Onu.PonPortID, service.UniPort.Onu.ID, service.UniPort.Onu.Sn(),
+ service.UniPort.PortNo, service.UniPort.ID, service.GemPort, service.HwAddress, ctag,
+ service.UsPonCTagPriority, service.Stream, req.GroupAddress)
+ }()
+ case bbsim.SubActionTypes_LEAVE:
+ go func() {
+ _ = igmp.SendIGMPLeaveGroupV2(service.UniPort.Onu.PonPortID, service.UniPort.Onu.ID, service.UniPort.Onu.Sn(),
+ service.UniPort.PortNo, service.UniPort.ID, service.GemPort, service.HwAddress, ctag,
+ service.UsPonCTagPriority, service.Stream, req.GroupAddress)
+ }()
+ case bbsim.SubActionTypes_JOINV3:
+ go func() {
+ _ = igmp.SendIGMPMembershipReportV3(service.UniPort.Onu.PonPortID, service.UniPort.Onu.ID, service.UniPort.Onu.Sn(),
+ service.UniPort.PortNo, service.UniPort.ID, service.GemPort, service.HwAddress, ctag,
+ service.UsPonCTagPriority, service.Stream, req.GroupAddress)
+ }()
}
}
}
-
- if success {
- res.StatusCode = int32(codes.OK)
- if len(startedOn) > 0 {
- res.Message = fmt.Sprintf("IGMP %s sent on Services %s for ONU %s.",
- event, fmt.Sprintf("%v", startedOn), onu.Sn())
- } else {
- res.Message = "No service requires IGMP"
- }
- logger.WithFields(log.Fields{
- "OnuSn": req.OnuReq.SerialNumber,
- "subAction": req.SubActionVal,
- "GroupAddress": req.GroupAddress,
- "Message": res.Message,
- }).Info("Processed IGMP request for ONU")
- } else {
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = fmt.Sprintf("%v", errors)
- logger.WithFields(log.Fields{
- "OnuSn": req.OnuReq.SerialNumber,
- "subAction": req.SubActionVal,
- "GroupAddress": req.GroupAddress,
- "Message": res.Message,
- }).Error("Error while processing IGMP request for ONU")
- }
-
}
-
return res, nil
}
diff --git a/internal/bbsim/devices/services.go b/internal/bbsim/devices/services.go
index 458e289..4ac1d39 100644
--- a/internal/bbsim/devices/services.go
+++ b/internal/bbsim/devices/services.go
@@ -471,7 +471,7 @@
_ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, tag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, priority, s.Stream)
} else if msg.Type == packetHandlers.IGMP {
log.Warn(hex.EncodeToString(msg.Packet.Data()))
- _ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
+ _ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
}
}
}
@@ -540,7 +540,7 @@
"UniId": s.UniPort.ID,
"Name": s.Name,
}).Debug("Received IGMPMembershipReportV2 message on ONU channel")
- _ = igmp.SendIGMPMembershipReportV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
+ _ = igmp.SendIGMPMembershipReportV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
case bbsimTypes.IGMPLeaveGroup:
igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
serviceLogger.WithFields(log.Fields{
@@ -552,7 +552,7 @@
"UniId": s.UniPort.ID,
"Name": s.Name,
}).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
- _ = igmp.SendIGMPLeaveGroupV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
+ _ = igmp.SendIGMPLeaveGroupV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
case bbsimTypes.IGMPMembershipReportV3:
igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
serviceLogger.WithFields(log.Fields{
@@ -564,7 +564,7 @@
"UniId": s.UniPort.ID,
"Name": s.Name,
}).Debug("Received IGMPMembershipReportV3 message on ONU channel")
- _ = igmp.SendIGMPMembershipReportV3(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
+ _ = igmp.SendIGMPMembershipReportV3(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
}
}
diff --git a/internal/bbsim/responders/igmp/igmp.go b/internal/bbsim/responders/igmp/igmp.go
index ea3a901..fe30cd5 100644
--- a/internal/bbsim/responders/igmp/igmp.go
+++ b/internal/bbsim/responders/igmp/igmp.go
@@ -17,10 +17,13 @@
"encoding/binary"
"encoding/hex"
"errors"
- "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
+ "fmt"
"net"
+ "strconv"
"time"
+ "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
+
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
bbsim "github.com/opencord/bbsim/internal/bbsim/types"
@@ -28,7 +31,7 @@
log "github.com/sirupsen/logrus"
)
-func SendIGMPLeaveGroupV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+func SendIGMPLeaveGroupV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, uniId uint32,
gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
log.WithFields(log.Fields{
"OnuId": onuId,
@@ -49,6 +52,13 @@
return err
}
+ // For IGMP testing, if voltha is not connected we do not have
+ // gemPortId, so set a unique gemPortId per ONU
+ if gemPortId == 0 {
+ gid, _ := strconv.ParseUint(fmt.Sprintf("%d%d", ponPortId, onuId), 10, 32)
+ gemPortId = uint32(gid)
+ }
+
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
@@ -57,7 +67,7 @@
Pkt: pkt,
PortNo: portNo,
OnuId: onuId,
- UniId: 0, // FIXME: When multi-uni support comes in, this hardcoding has to be removed
+ UniId: uniId,
},
}
//Sending IGMP packets
@@ -75,7 +85,7 @@
return nil
}
-func SendIGMPMembershipReportV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+func SendIGMPMembershipReportV2(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, uniId uint32,
gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
igmp := createIGMPV2MembershipReportPacket(groupAddress)
@@ -91,6 +101,13 @@
return err
}
+ // For IGMP testing, if voltha is not connected we do not have
+ // gemPortId, so set a unique gemPortId per ONU
+ if gemPortId == 0 {
+ gid, _ := strconv.ParseUint(fmt.Sprintf("%d%d", ponPortId, onuId), 10, 32)
+ gemPortId = uint32(gid)
+ }
+
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
@@ -99,7 +116,7 @@
Pkt: pkt,
PortNo: portNo,
OnuId: onuId,
- UniId: 0,
+ UniId: uniId,
},
}
//Sending IGMP packets
@@ -124,7 +141,7 @@
return nil
}
-func SendIGMPMembershipReportV3(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+func SendIGMPMembershipReportV3(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, uniId uint32,
gemPortId uint32, macAddress net.HardwareAddr, cTag int, pbit uint8, stream bbsim.Stream, groupAddress string) error {
log.WithFields(log.Fields{
@@ -146,6 +163,13 @@
return err
}
+ // For IGMP testing, if voltha is not connected we do not have
+ // gemPortId, so set a unique gemPortId per ONU
+ if gemPortId == 0 {
+ gid, _ := strconv.ParseUint(fmt.Sprintf("%d%d", ponPortId, onuId), 10, 32)
+ gemPortId = uint32(gid)
+ }
+
data := &openolt.Indication_PktInd{
PktInd: &openolt.PacketIndication{
IntfType: "pon",
@@ -154,7 +178,7 @@
Pkt: pkt,
PortNo: portNo,
OnuId: onuId,
- UniId: 0, // FIXME: When multi-uni support comes in, this hardcoding has to be removed
+ UniId: uniId,
},
}
//Sending IGMP packets
@@ -171,7 +195,7 @@
return nil
}
-func HandleNextPacket(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32,
+func HandleNextPacket(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, uniId uint32,
gemPortId uint32, macAddress net.HardwareAddr, pkt gopacket.Packet, cTag int, pbit uint8, stream bbsim.Stream) error {
igmpLayer := pkt.Layer(layers.LayerTypeIGMP)
@@ -192,7 +216,7 @@
igmp := igmpLayer.(*layers.IGMPv1or2)
if igmp.Type == layers.IGMPMembershipQuery {
- _ = SendIGMPMembershipReportV2(ponPortId, onuId, serialNumber, portNo, gemPortId, macAddress,
+ _ = SendIGMPMembershipReportV2(ponPortId, onuId, serialNumber, portNo, uniId, gemPortId, macAddress,
cTag, pbit, stream, igmp.GroupAddress.String())
}
@@ -269,13 +293,19 @@
EthernetType: layers.EthernetTypeIPv4,
}
+ destinationIP := igmp.GroupAddress
+ if igmp.Version == 3 && igmp.Type == layers.IGMPMembershipReportV3 {
+ //All IGMPv3-capable multicast routers
+ destinationIP = net.ParseIP("224.0.0.22")
+ }
+
ipLayer := &layers.IPv4{
Version: 4,
TOS: 0x10,
Id: 0,
TTL: 128,
SrcIP: []byte{0, 0, 0, 0},
- DstIP: igmp.GroupAddress,
+ DstIP: destinationIP,
Protocol: layers.IPProtocolIGMP,
Options: []layers.IPv4Option{{OptionType: 148, OptionLength: 4, OptionData: make([]byte, 0)}}, //Adding router alert option
}
diff --git a/internal/bbsim/responders/igmp/igmp_test.go b/internal/bbsim/responders/igmp/igmp_test.go
index b13e473..d6442a3 100644
--- a/internal/bbsim/responders/igmp/igmp_test.go
+++ b/internal/bbsim/responders/igmp/igmp_test.go
@@ -19,13 +19,14 @@
import (
"encoding/hex"
"fmt"
+ "net"
+ "testing"
+
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/opencord/voltha-protos/v5/go/openolt"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
- "net"
- "testing"
)
type mockStream struct {
@@ -64,7 +65,7 @@
fmt.Println(packet.Layers())
- err := HandleNextPacket(0, 0, "FOO", 1, 1024, mac, packet, 55, 5, stream)
+ err := HandleNextPacket(0, 0, "FOO", 1, 1024, 0, mac, packet, 55, 5, stream)
assert.Nil(t, err)
assert.Equal(t, 1, stream.CallCount)
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index 80e5f0d..a6f070c 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -38,8 +38,10 @@
)
type OnuSnString string
+type UniId int
type IgmpSubAction string
type GroupAddress string
+type VLAN int
const IgmpJoinKey string = "join"
const IgmpLeaveKey string = "leave"
@@ -92,9 +94,11 @@
type ONUIgmp struct {
Args struct {
OnuSn OnuSnString
+ UniId UniId
SubAction IgmpSubAction
GroupAddress GroupAddress
} `positional-args:"yes" required:"yes"`
+ VLAN VLAN `short:"v" long:"vlan" description:"VLAN to set"`
}
type ONUTrafficSchedulers struct {
@@ -297,10 +301,6 @@
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
defer cancel()
- req := pb.ONURequest{
- SerialNumber: string(options.Args.OnuSn),
- }
-
var subActionVal pb.SubActionTypes
if string(options.Args.SubAction) == IgmpJoinKey {
subActionVal = pb.SubActionTypes_JOIN
@@ -311,18 +311,23 @@
}
igmpReq := pb.IgmpRequest{
- OnuReq: &req,
- SubActionVal: subActionVal,
- GroupAddress: string(options.Args.GroupAddress),
+ OnuSerialNumber: string(options.Args.OnuSn),
+ UniID: int32(options.Args.UniId),
+ SubActionVal: subActionVal,
+ GroupAddress: string(options.Args.GroupAddress),
+ VLAN: int32(options.VLAN),
}
- res, err := client.GetONU(ctx, igmpReq.OnuReq)
+ req := &pb.ONURequest{
+ SerialNumber: string(options.Args.OnuSn),
+ }
+ res, err := client.GetONU(ctx, req)
if err != nil {
log.WithFields(log.Fields{
"SerialNumber": options.Args.OnuSn,
}).Errorf("Cannot not get details on ONU error: %v", err)
}
log.WithFields(log.Fields{
- "SerialNumber": igmpReq.OnuReq.SerialNumber,
+ "SerialNumber": igmpReq.OnuSerialNumber,
}).Debugf("ONU has identified : %s", res)
igmpRes, igmpErr := client.ChangeIgmpState(ctx, &igmpReq)