Merge "[SEBA-843] Storing PortNo in the ONU Device struct so that it can be passed with the packetIndications"
diff --git a/api/bbsim/bbsim.proto b/api/bbsim/bbsim.proto
index bc76a92..85581fc 100644
--- a/api/bbsim/bbsim.proto
+++ b/api/bbsim/bbsim.proto
@@ -45,6 +45,7 @@
int32 STag = 6;
int32 CTag = 7;
string HwAddress = 8;
+ int32 PortNo = 9;
}
message ONUs {
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index 1b823d8..7f42f89 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -42,6 +42,7 @@
STag: int32(o.STag),
CTag: int32(o.CTag),
HwAddress: o.HwAddress.String(),
+ PortNo: int32(o.PortNo),
}
onus.Items = append(onus.Items, &onu)
}
@@ -68,6 +69,7 @@
STag: int32(onu.STag),
CTag: int32(onu.CTag),
HwAddress: onu.HwAddress.String(),
+ PortNo: int32(onu.PortNo),
}
return &res, nil
}
diff --git a/internal/bbsim/devices/messageTypes.go b/internal/bbsim/devices/messageTypes.go
index 6d3f076..fe6abef 100644
--- a/internal/bbsim/devices/messageTypes.go
+++ b/internal/bbsim/devices/messageTypes.go
@@ -75,7 +75,7 @@
type OnuDiscIndicationMessage struct {
OperState OperState
- Onu Onu
+ Onu *Onu
}
type OnuIndicationMessage struct {
diff --git a/internal/bbsim/devices/nni.go b/internal/bbsim/devices/nni.go
index 05585fc..30104fc 100644
--- a/internal/bbsim/devices/nni.go
+++ b/internal/bbsim/devices/nni.go
@@ -34,6 +34,22 @@
dhcpServerIp = "182.21.0.128"
)
+type Executor interface {
+ Command(name string, arg ...string) Runnable
+}
+
+type DefaultExecutor struct{}
+
+func (d DefaultExecutor) Command(name string, arg ...string) Runnable {
+ return exec.Command(name, arg...)
+}
+
+type Runnable interface {
+ Run() error
+}
+
+var executor = DefaultExecutor{}
+
type NniPort struct {
// BBSIM Internals
ID uint32
@@ -51,7 +67,7 @@
}),
Type: "nni",
}
- createNNIPair(olt)
+ createNNIPair(executor, olt)
return nniPort, nil
}
@@ -89,21 +105,21 @@
return nil
}
-// createNNIBridge will create a veth bridge to fake the connection between the NNI port
-// and something upstream, in this case a DHCP server.
-// It is also responsible to start the DHCP server itself
-func createNNIPair(olt *OltDevice) error {
+//createNNIBridge will create a veth bridge to fake the connection between the NNI port
+//and something upstream, in this case a DHCP server.
+//It is also responsible to start the DHCP server itself
+func createNNIPair(executor Executor, olt *OltDevice) error {
- if err := exec.Command("ip", "link", "add", nniVeth, "type", "veth", "peer", "name", upstreamVeth).Run(); err != nil {
+ if err := executor.Command("ip", "link", "add", nniVeth, "type", "veth", "peer", "name", upstreamVeth).Run(); err != nil {
nniLogger.Errorf("Couldn't create veth pair between %s and %s", nniVeth, upstreamVeth)
return err
}
- if err := setVethUp(nniVeth); err != nil {
+ if err := setVethUp(executor, nniVeth); err != nil {
return err
}
- if err := setVethUp(upstreamVeth); err != nil {
+ if err := setVethUp(executor, upstreamVeth); err != nil {
return err
}
@@ -120,21 +136,21 @@
}
// setVethUp is responsible to activate a virtual interface
-func setVethUp(vethName string) error {
- if err := exec.Command("ip", "link", "set", vethName, "up").Run(); err != nil {
+func setVethUp(executor Executor, vethName string) error {
+ if err := executor.Command("ip", "link", "set", vethName, "up").Run(); err != nil {
nniLogger.Errorf("Couldn't change interface %s state to up: %v", vethName, err)
return err
}
return nil
}
-func startDHCPServer() error {
+var startDHCPServer = func() error {
if err := exec.Command("ip", "addr", "add", dhcpServerIp, "dev", upstreamVeth).Run(); err != nil {
nniLogger.Errorf("Couldn't assing ip %s to interface %s: %v", dhcpServerIp, upstreamVeth, err)
return err
}
- if err := setVethUp(upstreamVeth); err != nil {
+ if err := setVethUp(executor, upstreamVeth); err != nil {
return err
}
@@ -168,7 +184,7 @@
return handle, nil
}
-func listenOnVeth(vethName string) (chan *types.PacketMsg, error) {
+var listenOnVeth = func(vethName string) (chan *types.PacketMsg, error) {
handle, err := getVethHandler(vethName)
if err != nil {
diff --git a/internal/bbsim/devices/nni_test.go b/internal/bbsim/devices/nni_test.go
new file mode 100644
index 0000000..60856c6
--- /dev/null
+++ b/internal/bbsim/devices/nni_test.go
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/mocking
+package devices
+
+import (
+ "errors"
+ "github.com/opencord/bbsim/internal/bbsim/types"
+ "gotest.tools/assert"
+ "testing"
+)
+
+func TestSetVethUpSuccess(t *testing.T) {
+ spy := &ExecutorSpy{
+ Calls: make(map[int][]string),
+ }
+ err := setVethUp(spy, "test_veth")
+ assert.Equal(t, spy.CommandCallCount, 1)
+ assert.Equal(t, spy.Calls[1][2], "test_veth")
+ assert.Equal(t, err, nil)
+}
+
+func TestSetVethUpFail(t *testing.T) {
+ spy := &ExecutorSpy{
+ failRun: true,
+ Calls: make(map[int][]string),
+ }
+ err := setVethUp(spy, "test_veth")
+ assert.Equal(t, spy.CommandCallCount, 1)
+ assert.Equal(t, err.Error(), "fake-error")
+}
+
+func TestCreateNNIPair(t *testing.T) {
+
+ startDHCPServerCalled := false
+ _startDHCPServer := startDHCPServer
+ defer func() { startDHCPServer = _startDHCPServer }()
+ startDHCPServer = func() error {
+ startDHCPServerCalled = true
+ return nil
+ }
+
+ listenOnVethCalled := false
+ _listenOnVeth := listenOnVeth
+ defer func() { listenOnVeth = _listenOnVeth }()
+ listenOnVeth = func(vethName string) (chan *types.PacketMsg, error) {
+ listenOnVethCalled = true
+ return make(chan *types.PacketMsg, 1), nil
+ }
+ spy := &ExecutorSpy{
+ failRun: false,
+ Calls: make(map[int][]string),
+ }
+
+ olt := OltDevice{}
+
+ err := createNNIPair(spy, &olt)
+
+ assert.Equal(t, spy.CommandCallCount, 3)
+ assert.Equal(t, startDHCPServerCalled, true)
+ assert.Equal(t, listenOnVethCalled, true)
+ assert.Equal(t, err, nil)
+ assert.Assert(t, olt.nniPktInChannel != nil)
+}
+
+type ExecutorSpy struct {
+ failRun bool
+
+ CommandCallCount int
+ RunCallCount int
+ Calls map[int][]string
+}
+
+func (s *ExecutorSpy) Command(name string, arg ...string) Runnable {
+ s.CommandCallCount++
+
+ s.Calls[s.CommandCallCount] = arg
+
+ return s
+}
+
+func (s *ExecutorSpy) Run() error {
+ s.RunCallCount++
+ if s.failRun {
+ return errors.New("fake-error")
+ }
+ return nil
+}
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index 864a88e..c3a62ff 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -50,17 +50,17 @@
apiDoneChannel *chan bool
nniPktInChannel chan *bbsim.PacketMsg
- Pons []PonPort
- Nnis []NniPort
+ Pons []*PonPort
+ Nnis []*NniPort
// OLT Attributes
OperState *fsm.FSM
}
-var olt = OltDevice{}
+var olt OltDevice
-func GetOLT() OltDevice {
- return olt
+func GetOLT() *OltDevice {
+ return &olt
}
func CreateOLT(seq int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, oltDoneChannel *chan bool, apiDoneChannel *chan bool, group *sync.WaitGroup) OltDevice {
@@ -80,8 +80,8 @@
NumNni: nni,
NumPon: pon,
NumOnuPerPon: onuPerPon,
- Pons: []PonPort{},
- Nnis: []NniPort{},
+ Pons: []*PonPort{},
+ Nnis: []*NniPort{},
channel: make(chan Message),
oltDoneChannel: oltDoneChannel,
apiDoneChannel: apiDoneChannel,
@@ -110,7 +110,7 @@
oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
}
- olt.Nnis = append(olt.Nnis, nniPort)
+ olt.Nnis = append(olt.Nnis, &nniPort)
// create PON ports
availableCTag := cTagInit
@@ -120,6 +120,7 @@
ID: uint32(i),
Type: "pon",
Olt: olt,
+ Onus: []*Onu{},
}
p.OperState = getOperStateFSM(func(e *fsm.Event) {
oltLogger.WithFields(log.Fields{
@@ -129,13 +130,12 @@
// create ONU devices
for j := 0; j < onuPerPon; j++ {
- //o := CreateONU(olt, p, uint32(onuId))
o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag)
p.Onus = append(p.Onus, o)
availableCTag = availableCTag + 1
}
- olt.Pons = append(olt.Pons, p)
+ olt.Pons = append(olt.Pons, &p)
}
newOltServer(olt)
@@ -246,7 +246,7 @@
func (o OltDevice) getPonById(id uint32) (*PonPort, error) {
for _, pon := range o.Pons {
if pon.ID == id {
- return &pon, nil
+ return pon, nil
}
}
return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
@@ -255,7 +255,7 @@
func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
for _, nni := range o.Nnis {
if nni.ID == id {
- return &nni, nil
+ return nni, nil
}
}
return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
@@ -375,7 +375,7 @@
"IntfType": "nni",
"IntfId": nniId,
"Pkt": message.Pkt.Data(),
- }).Info("Can't find Dst MacAddress in packet")
+ }).Error("Can't find Dst MacAddress in packet")
return
}
@@ -386,7 +386,7 @@
"IntfId": nniId,
"Pkt": message.Pkt.Data(),
"MacAddress": onuMac.String(),
- }).Info("Can't find ONU with MacAddress")
+ }).Error("Can't find ONU with MacAddress")
return
}
@@ -421,7 +421,7 @@
for _, pon := range o.Pons {
for _, onu := range pon.Onus {
if onu.Sn() == serialNumber {
- return &onu, nil
+ return onu, nil
}
}
}
@@ -436,7 +436,7 @@
for _, pon := range o.Pons {
for _, onu := range pon.Onus {
if onu.HwAddress.String() == mac.String() {
- return &onu, nil
+ return onu, nil
}
}
}
@@ -531,8 +531,22 @@
"FlowId": flow.FlowId,
}).Debugf("This is an OLT flow")
} else {
- pon, _ := o.getPonById(uint32(flow.AccessIntfId))
- onu, _ := pon.getOnuById(uint32(flow.OnuId))
+ pon, err := o.getPonById(uint32(flow.AccessIntfId))
+ if err != nil {
+ oltLogger.WithFields(log.Fields{
+ "OnuId": flow.OnuId,
+ "IntfId": flow.AccessIntfId,
+ "err": err,
+ }).Error("Can't find PonPort")
+ }
+ onu, err := pon.getOnuById(uint32(flow.OnuId))
+ if err != nil {
+ oltLogger.WithFields(log.Fields{
+ "OnuId": flow.OnuId,
+ "IntfId": flow.AccessIntfId,
+ "err": err,
+ }).Error("Can't find Onu")
+ }
msg := Message{
Type: FlowUpdate,
@@ -606,8 +620,22 @@
}
func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
- pon, _ := o.getPonById(onuPkt.IntfId)
- onu, _ := pon.getOnuById(onuPkt.OnuId)
+ pon, err := o.getPonById(onuPkt.IntfId)
+ if err != nil {
+ oltLogger.WithFields(log.Fields{
+ "OnuId": onuPkt.OnuId,
+ "IntfId": onuPkt.IntfId,
+ "err": err,
+ }).Error("Can't find PonPort")
+ }
+ onu, err := pon.getOnuById(onuPkt.OnuId)
+ if err != nil {
+ oltLogger.WithFields(log.Fields{
+ "OnuId": onuPkt.OnuId,
+ "IntfId": onuPkt.IntfId,
+ "err": err,
+ }).Error("Can't find Onu")
+ }
oltLogger.WithFields(log.Fields{
"IntfId": onu.PonPortID,
diff --git a/internal/bbsim/devices/olt_test.go b/internal/bbsim/devices/olt_test.go
index f83fc62..bcb6f77 100644
--- a/internal/bbsim/devices/olt_test.go
+++ b/internal/bbsim/devices/olt_test.go
@@ -41,9 +41,9 @@
HwAddress: net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(pon.ID), byte(onuId)},
}
onu.SerialNumber = onu.NewSN(olt.ID, pon.ID, onu.ID)
- pon.Onus = append(pon.Onus, onu)
+ pon.Onus = append(pon.Onus, &onu)
}
- olt.Pons = append(olt.Pons, pon)
+ olt.Pons = append(olt.Pons, &pon)
}
return olt
}
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index dfbd9ce..7d36bfd 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -34,11 +34,15 @@
})
type Onu struct {
- ID uint32
- PonPortID uint32
- PonPort PonPort
- STag int
- CTag int
+ ID uint32
+ PonPortID uint32
+ PonPort PonPort
+ STag int
+ CTag int
+ // PortNo comes with flows and it's used when sending packetIndications,
+ // There is one PortNo per UNI Port, for now we're only storing the first one
+ // FIXME add support for multiple UNIs
+ PortNo uint32
HwAddress net.HardwareAddr
InternalState *fsm.FSM
@@ -52,7 +56,7 @@
return onuSnToString(o.SerialNumber)
}
-func CreateONU(olt OltDevice, pon PonPort, id uint32, sTag int, cTag int) Onu {
+func CreateONU(olt OltDevice, pon PonPort, id uint32, sTag int, cTag int) *Onu {
o := Onu{
ID: id,
@@ -61,8 +65,8 @@
STag: sTag,
CTag: cTag,
HwAddress: net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(pon.ID), byte(id)},
- // NOTE can we combine everything in a single Channel?
- Channel: make(chan Message, 2048),
+ PortNo: 0,
+ Channel: make(chan Message, 2048),
}
o.SerialNumber = o.NewSN(olt.ID, pon.ID, o.ID)
@@ -162,7 +166,7 @@
},
},
)
- return o
+ return &o
}
func (o Onu) logStateChange(src string, dst string) {
@@ -201,21 +205,22 @@
o.handleFlowUpdate(msg, stream)
case StartEAPOL:
log.Infof("Receive StartEAPOL message on ONU Channel")
- eapol.SendEapStart(o.ID, o.PonPortID, o.Sn(), o.HwAddress, o.InternalState, stream)
+ eapol.SendEapStart(o.ID, o.PonPortID, o.Sn(), o.PortNo, o.HwAddress, o.InternalState, stream)
case StartDHCP:
log.Infof("Receive StartDHCP message on ONU Channel")
- dhcp.SendDHCPDiscovery(o.PonPortID, o.ID, o.Sn(), o.InternalState, o.HwAddress, o.CTag, stream)
+ // FIXME use id, ponId as SendEapStart
+ dhcp.SendDHCPDiscovery(o.PonPortID, o.ID, o.Sn(), o.PortNo, o.InternalState, o.HwAddress, o.CTag, stream)
case OnuPacketOut:
msg, _ := message.Data.(OnuPacketOutMessage)
pkt := msg.Packet
etherType := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet).EthernetType
if etherType == layers.EthernetTypeEAPOL {
- eapol.HandleNextPacket(msg.OnuId, msg.IntfId, o.Sn(), o.InternalState, msg.Packet, stream)
+ eapol.HandleNextPacket(msg.OnuId, msg.IntfId, o.Sn(), o.PortNo, o.InternalState, msg.Packet, stream)
} else if packetHandlers.IsDhcpPacket(pkt) {
// NOTE here we receive packets going from the DHCP Server to the ONU
// for now we expect them to be double-tagged, but ideally the should be single tagged
- dhcp.HandleNextPacket(o.ID, o.PonPortID, o.Sn(), o.HwAddress, o.CTag, o.InternalState, msg.Packet, stream)
+ dhcp.HandleNextPacket(o.ID, o.PonPortID, o.Sn(), o.PortNo, o.HwAddress, o.CTag, o.InternalState, msg.Packet, stream)
}
case DyingGaspIndication:
msg, _ := message.Data.(DyingGaspIndicationMessage)
@@ -349,14 +354,20 @@
onuLogger.WithFields(log.Fields{
"IntfId": o.PonPortID,
- "SerialNumber": o.SerialNumber,
+ "SerialNumber": o.Sn(),
"omciPacket": msg.omciMsg.Pkt,
}).Tracef("Received OMCI message")
var omciInd openolt.OmciIndication
respPkt, err := omci.OmciSim(o.PonPortID, o.ID, HexDecode(msg.omciMsg.Pkt))
if err != nil {
- onuLogger.Errorf("Error handling OMCI message %v", msg)
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "SerialNumber": o.Sn(),
+ "omciPacket": omciInd.Pkt,
+ "msg": msg,
+ }).Errorf("Error handling OMCI message %v", msg)
+ return
}
omciInd.IntfId = o.PonPortID
@@ -365,16 +376,34 @@
omci := &openolt.Indication_OmciInd{OmciInd: &omciInd}
if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
- onuLogger.Errorf("send omci indication failed: %v", err)
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "SerialNumber": o.Sn(),
+ "omciPacket": omciInd.Pkt,
+ "msg": msg,
+ }).Errorf("send omci indication failed: %v", err)
+ return
}
onuLogger.WithFields(log.Fields{
"IntfId": o.PonPortID,
- "SerialNumber": o.SerialNumber,
+ "SerialNumber": o.Sn(),
"omciPacket": omciInd.Pkt,
}).Tracef("Sent OMCI message")
}
-func (o Onu) handleFlowUpdate(msg OnuFlowUpdateMessage, stream openolt.Openolt_EnableIndicationServer) {
+func (o *Onu) storePortNumber(portNo uint32) {
+ // FIXME this is a workaround to always use the SN-1 entry in sadis,
+ // we need to add support for multiple UNIs
+ // the action plan is:
+ // - refactor the omci-sim library to use https://github.com/cboling/omci instead of canned messages
+ // - change the library so that it reports a single UNI and remove this workaroung
+ // - add support for multiple UNIs in BBSim
+ if portNo < o.PortNo {
+ o.PortNo = portNo
+ }
+}
+
+func (o *Onu) handleFlowUpdate(msg OnuFlowUpdateMessage, stream openolt.Openolt_EnableIndicationServer) {
onuLogger.WithFields(log.Fields{
"DstPort": msg.Flow.Classifier.DstPort,
"EthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
@@ -392,6 +421,11 @@
}).Debug("ONU receives Flow")
if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
+ // NOTE storing the PortNO, it's needed when sending PacketIndications
+ if o.PortNo == 0 {
+ o.storePortNumber(uint32(msg.Flow.PortNo))
+ }
+
// NOTE if we receive the EAPOL flows but we don't have GemPorts
// go an intermediate state, otherwise start auth
if o.InternalState.Is("enabled") {
diff --git a/internal/bbsim/devices/pon.go b/internal/bbsim/devices/pon.go
index 0e67e51..374b1b9 100644
--- a/internal/bbsim/devices/pon.go
+++ b/internal/bbsim/devices/pon.go
@@ -28,7 +28,7 @@
// BBSIM Internals
ID uint32
NumOnu int
- Onus []Onu
+ Onus []*Onu
Olt OltDevice
// PON Attributes
@@ -41,7 +41,7 @@
func (p PonPort) getOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
for _, onu := range p.Onus {
if bytes.Equal(onu.SerialNumber.VendorSpecific, sn.VendorSpecific) {
- return &onu, nil
+ return onu, nil
}
}
return nil, errors.New(fmt.Sprintf("Cannot find Onu with serial number %d in PonPort %d", sn, p.ID))
@@ -50,7 +50,7 @@
func (p PonPort) getOnuById(id uint32) (*Onu, error) {
for _, onu := range p.Onus {
if onu.ID == id {
- return &onu, nil
+ return onu, nil
}
}
return nil, errors.New(fmt.Sprintf("Cannot find Onu with id %d in PonPort %d", id, p.ID))
diff --git a/internal/bbsim/responders/dhcp/dhcp.go b/internal/bbsim/responders/dhcp/dhcp.go
index 64e83dd..c7ae75c 100644
--- a/internal/bbsim/responders/dhcp/dhcp.go
+++ b/internal/bbsim/responders/dhcp/dhcp.go
@@ -194,7 +194,7 @@
return 0, errors.New("Failed to extract MsgType from dhcp")
}
-func sendDHCPPktIn(msg bbsim.ByteMsg, stream openolt.Openolt_EnableIndicationServer) error {
+func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, stream bbsim.Stream) error {
// FIXME unify sendDHCPPktIn and sendEapolPktIn methods
gemid, err := GetGemPortId(msg.IntfId, msg.OnuId)
if err != nil {
@@ -205,7 +205,11 @@
return err
}
data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
- IntfType: "pon", IntfId: msg.IntfId, GemportId: uint32(gemid), Pkt: msg.Bytes,
+ IntfType: "pon",
+ IntfId: msg.IntfId,
+ GemportId: uint32(gemid),
+ Pkt: msg.Bytes,
+ PortNo: portNo,
}}
if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
@@ -215,7 +219,7 @@
return nil
}
-func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, onuHwAddress net.HardwareAddr, cTag int, stream openolt.Openolt_EnableIndicationServer) error {
+func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuHwAddress net.HardwareAddr, cTag int, stream openolt.Openolt_EnableIndicationServer) error {
dhcp := createDHCPReq(ponPortId, onuId)
pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
@@ -232,7 +236,7 @@
Bytes: pkt,
}
- if err := sendDHCPPktIn(msg, stream); err != nil {
+ if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
return err
}
dhcpLogger.WithFields(log.Fields{
@@ -255,7 +259,7 @@
return nil
}
-func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serialNumber string, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, cTag int, stream openolt.Openolt_EnableIndicationServer) error {
+func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, cTag int, stream bbsim.Stream) error {
dhcp := createDHCPDisc(ponPortId, onuId)
pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
if err != nil {
@@ -271,7 +275,7 @@
Bytes: pkt,
}
- if err := sendDHCPPktIn(msg, stream); err != nil {
+ if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
return err
}
@@ -293,7 +297,7 @@
return nil
}
-func HandleNextPacket(onuId uint32, ponPortId uint32, serialNumber string, onuHwAddress net.HardwareAddr, cTag int, onuStateMachine *fsm.FSM, pkt gopacket.Packet, stream openolt.Openolt_EnableIndicationServer) error {
+func HandleNextPacket(onuId uint32, ponPortId uint32, serialNumber string, portNo uint32, onuHwAddress net.HardwareAddr, cTag int, onuStateMachine *fsm.FSM, pkt gopacket.Packet, stream openolt.Openolt_EnableIndicationServer) error {
dhcpLayer, err := getDhcpLayer(pkt)
if err != nil {
@@ -322,7 +326,7 @@
if dhcpLayer.Operation == layers.DHCPOpReply {
if dhcpMessageType == layers.DHCPMsgTypeOffer {
- if err := sendDHCPRequest(ponPortId, onuId, serialNumber, onuHwAddress, cTag, stream); err != nil {
+ if err := sendDHCPRequest(ponPortId, onuId, serialNumber, portNo, onuHwAddress, cTag, stream); err != nil {
dhcpLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
diff --git a/internal/bbsim/responders/dhcp/dhcp_test.go b/internal/bbsim/responders/dhcp/dhcp_test.go
index 0733cc0..6aa8060 100644
--- a/internal/bbsim/responders/dhcp/dhcp_test.go
+++ b/internal/bbsim/responders/dhcp/dhcp_test.go
@@ -27,7 +27,6 @@
)
// MOCKS
-var calledSend = 0
var dhcpStateMachine = fsm.NewFSM(
"dhcp_started",
@@ -42,49 +41,55 @@
type mockStreamSuccess struct {
grpc.ServerStream
+ CallCount int
+ Calls map[int]*openolt.PacketIndication
+ fail bool
}
-func (s mockStreamSuccess) Send(ind *openolt.Indication) error {
- calledSend++
+func (s *mockStreamSuccess) Send(ind *openolt.Indication) error {
+ s.CallCount++
+ if s.fail {
+ return errors.New("fake-error")
+ }
+ s.Calls[s.CallCount] = ind.GetPktInd()
return nil
}
-type mockStreamError struct {
- grpc.ServerStream
-}
-
-func (s mockStreamError) Send(ind *openolt.Indication) error {
- calledSend++
- return errors.New("stream-error")
-}
-
// TESTS
func TestSendDHCPDiscovery(t *testing.T) {
- calledSend = 0
dhcpStateMachine.SetState("dhcp_started")
+ var onuId uint32 = 1
+ var gemPortId uint16 = 1
+ var ponPortId uint32 = 0
+ var serialNumber = "BBSM00000001"
+ var mac = net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(ponPortId), byte(onuId)}
+ var portNo uint32 = 16
+
// Save current function and restore at the end:
old := GetGemPortId
defer func() { GetGemPortId = old }()
GetGemPortId = func(intfId uint32, onuId uint32) (uint16, error) {
- return 1, nil
+ return gemPortId, nil
}
- var onuId uint32 = 1
- var ponPortId uint32 = 0
- var serialNumber string = "BBSM00000001"
- var mac = net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(ponPortId), byte(onuId)}
+ stream := &mockStreamSuccess{
+ Calls: make(map[int]*openolt.PacketIndication),
+ fail: false,
+ }
- stream := mockStreamSuccess{}
-
- if err := SendDHCPDiscovery(ponPortId, onuId, serialNumber, dhcpStateMachine, mac, 1, stream); err != nil {
+ if err := SendDHCPDiscovery(ponPortId, onuId, serialNumber, portNo, dhcpStateMachine, mac, 1, stream); err != nil {
t.Errorf("SendDHCPDiscovery returned an error: %v", err)
t.Fail()
}
- assert.Equal(t, calledSend, 1)
+ assert.Equal(t, stream.CallCount, 1)
+ assert.Equal(t, stream.Calls[1].PortNo, portNo)
+ assert.Equal(t, stream.Calls[1].IntfId, ponPortId)
+ assert.Equal(t, stream.Calls[1].IntfType, "pon")
+ assert.Equal(t, stream.Calls[1].GemportId, uint32(gemPortId))
assert.Equal(t, dhcpStateMachine.Current(), "dhcp_discovery_sent")
}
diff --git a/internal/bbsim/responders/eapol/eapol.go b/internal/bbsim/responders/eapol/eapol.go
index 6f2642e..f31a068 100644
--- a/internal/bbsim/responders/eapol/eapol.go
+++ b/internal/bbsim/responders/eapol/eapol.go
@@ -36,7 +36,7 @@
var eapolVersion uint8 = 1
var GetGemPortId = omci.GetGemPortId
-func sendEapolPktIn(msg bbsim.ByteMsg, stream openolt.Openolt_EnableIndicationServer) {
+func sendEapolPktIn(msg bbsim.ByteMsg, portNo uint32, stream openolt.Openolt_EnableIndicationServer) {
// FIXME unify sendDHCPPktIn and sendEapolPktIn methods
gemid, err := omci.GetGemPortId(msg.IntfId, msg.OnuId)
if err != nil {
@@ -47,7 +47,11 @@
return
}
data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
- IntfType: "pon", IntfId: msg.IntfId, GemportId: uint32(gemid), Pkt: msg.Bytes,
+ IntfType: "pon",
+ IntfId: msg.IntfId,
+ GemportId: uint32(gemid),
+ Pkt: msg.Bytes,
+ PortNo: portNo,
}}
if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
@@ -129,7 +133,7 @@
return nil
}
-func SendEapStart(onuId uint32, ponPortId uint32, serialNumber string, macAddress net.HardwareAddr, onuStateMachine *fsm.FSM, stream openolt.Openolt_EnableIndicationServer) error {
+func SendEapStart(onuId uint32, ponPortId uint32, serialNumber string, portNo uint32, macAddress net.HardwareAddr, onuStateMachine *fsm.FSM, stream bbsim.Stream) error {
// send the packet (hacked together)
gemId, err := GetGemPortId(ponPortId, onuId)
@@ -170,6 +174,7 @@
IntfId: ponPortId,
GemportId: uint32(gemId),
Pkt: msg,
+ PortNo: portNo,
},
}
@@ -187,9 +192,12 @@
return err
}
- if err != nil {
-
- }
+ eapolLogger.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "PortNo": portNo,
+ }).Debugf("Sent EapStart packet")
if err := onuStateMachine.Event("eap_start_sent"); err != nil {
eapolLogger.WithFields(log.Fields{
@@ -202,12 +210,21 @@
return nil
}
-func HandleNextPacket(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM, recvpkt gopacket.Packet, stream openolt.Openolt_EnableIndicationServer) {
+func HandleNextPacket(onuId uint32, ponPortId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, recvpkt gopacket.Packet, stream openolt.Openolt_EnableIndicationServer) {
+
eap, err := extractEAP(recvpkt)
if err != nil {
eapolLogger.Errorf("%s", err)
}
+ log.WithFields(log.Fields{
+ "eap.Code": eap.Code,
+ "eap.Type": eap.Type,
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ }).Tracef("HandleNextPacket")
+
if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeIdentity {
reseap := createEAPIdentityResponse(eap.Id)
pkt := createEAPOLPkt(reseap, onuId, ponPortId)
@@ -218,12 +235,13 @@
Bytes: pkt,
}
- sendEapolPktIn(msg, stream)
+ sendEapolPktIn(msg, portNo, stream)
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
"OnuSn": serialNumber,
- }).Infof("Sent EAPIdentityResponse packet")
+ "PortNo": portNo,
+ }).Debugf("Sent EAPIdentityResponse packet")
if err := onuStateMachine.Event("eap_response_identity_sent"); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
@@ -244,12 +262,13 @@
Bytes: pkt,
}
- sendEapolPktIn(msg, stream)
+ sendEapolPktIn(msg, portNo, stream)
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
"OnuSn": serialNumber,
- }).Infof("Sent EAPChallengeResponse packet")
+ "PortNo": portNo,
+ }).Debugf("Sent EAPChallengeResponse packet")
if err := onuStateMachine.Event("eap_response_challenge_sent"); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
@@ -262,7 +281,8 @@
"OnuId": onuId,
"IntfId": ponPortId,
"OnuSn": serialNumber,
- }).Infof("Received EAPSuccess packet")
+ "PortNo": portNo,
+ }).Debugf("Received EAPSuccess packet")
if err := onuStateMachine.Event("eap_response_success_received"); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
diff --git a/internal/bbsim/responders/eapol/eapol_test.go b/internal/bbsim/responders/eapol/eapol_test.go
index 6a80317..f32c6f8 100644
--- a/internal/bbsim/responders/eapol/eapol_test.go
+++ b/internal/bbsim/responders/eapol/eapol_test.go
@@ -27,7 +27,6 @@
)
// MOCKS
-var calledSend = 0
var eapolStateMachine = fsm.NewFSM(
"auth_started",
@@ -41,28 +40,33 @@
fsm.Callbacks{},
)
-type mockStreamSuccess struct {
+// params for the function under test
+var onuId uint32 = 1
+var gemPortId uint16 = 1
+var ponPortId uint32 = 0
+var serialNumber string = "BBSM00000001"
+var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
+var portNo uint32 = 16
+
+type mockStream struct {
grpc.ServerStream
+ CallCount int
+ Calls map[int]*openolt.PacketIndication
+ fail bool
}
-func (s mockStreamSuccess) Send(ind *openolt.Indication) error {
- calledSend++
+func (s *mockStream) Send(ind *openolt.Indication) error {
+ s.CallCount++
+ if s.fail {
+ return errors.New("fake-error")
+ }
+ s.Calls[s.CallCount] = ind.GetPktInd()
return nil
}
-type mockStreamError struct {
- grpc.ServerStream
-}
-
-func (s mockStreamError) Send(ind *openolt.Indication) error {
- calledSend++
- return errors.New("stream-error")
-}
-
// TESTS
func TestSendEapStartSuccess(t *testing.T) {
- calledSend = 0
eapolStateMachine.SetState("auth_started")
// Save current function and restore at the end:
@@ -70,31 +74,30 @@
defer func() { GetGemPortId = old }()
GetGemPortId = func(intfId uint32, onuId uint32) (uint16, error) {
- return 1, nil
+ return gemPortId, nil
}
- // params for the function under test
- var onuId uint32 = 1
- var ponPortId uint32 = 0
- var serialNumber string = "BBSM00000001"
+ stream := &mockStream{
+ Calls: make(map[int]*openolt.PacketIndication),
+ fail: false,
+ }
- var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
-
- stream := mockStreamSuccess{}
-
- if err := SendEapStart(onuId, ponPortId, serialNumber, macAddress, eapolStateMachine, stream); err != nil {
+ if err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, eapolStateMachine, stream); err != nil {
t.Errorf("SendEapStart returned an error: %v", err)
t.Fail()
}
- assert.Equal(t, calledSend, 1)
+ assert.Equal(t, stream.CallCount, 1)
+ assert.Equal(t, stream.Calls[1].PortNo, portNo)
+ assert.Equal(t, stream.Calls[1].IntfId, ponPortId)
+ assert.Equal(t, stream.Calls[1].IntfType, "pon")
+ assert.Equal(t, stream.Calls[1].GemportId, uint32(gemPortId))
assert.Equal(t, eapolStateMachine.Current(), "eap_start_sent")
}
func TestSendEapStartFailNoGemPort(t *testing.T) {
- calledSend = 0
eapolStateMachine.SetState("auth_started")
// Save current function and restore at the end:
@@ -105,16 +108,14 @@
return 0, errors.New("no-gem-port")
}
- // params for the function under test
- var onuId uint32 = 1
- var ponPortId uint32 = 0
- var serialNumber string = "BBSM00000001"
-
var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
- stream := mockStreamSuccess{}
+ stream := &mockStream{
+ Calls: make(map[int]*openolt.PacketIndication),
+ fail: false,
+ }
- err := SendEapStart(onuId, ponPortId, serialNumber, macAddress, eapolStateMachine, stream)
+ err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, eapolStateMachine, stream)
if err == nil {
t.Errorf("SendEapStart did not return an error")
t.Fail()
@@ -126,7 +127,7 @@
}
func TestSendEapStartFailStreamError(t *testing.T) {
- calledSend = 0
+
eapolStateMachine.SetState("auth_started")
// Save current function and restore at the end:
@@ -137,21 +138,18 @@
return 1, nil
}
- // params for the function under test
- var onuId uint32 = 1
- var ponPortId uint32 = 0
- var serialNumber = "BBSM00000001"
- var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
+ stream := &mockStream{
+ Calls: make(map[int]*openolt.PacketIndication),
+ fail: true,
+ }
- stream := mockStreamError{}
-
- err := SendEapStart(onuId, ponPortId, serialNumber, macAddress, eapolStateMachine, stream)
+ err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, eapolStateMachine, stream)
if err == nil {
t.Errorf("SendEapStart did not return an error")
t.Fail()
}
- assert.Equal(t, err.Error(), "stream-error")
+ assert.Equal(t, err.Error(), "fake-error")
assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
}
diff --git a/internal/bbsim/types/interfaces.go b/internal/bbsim/types/interfaces.go
new file mode 100644
index 0000000..c408697
--- /dev/null
+++ b/internal/bbsim/types/interfaces.go
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package types
+
+import "github.com/opencord/voltha-protos/go/openolt"
+
+// represent a gRPC stream
+type Stream interface {
+ Send(*openolt.Indication) error
+}
diff --git a/internal/bbsim/types/types.go b/internal/bbsim/types/types.go
index aa3740d..e5d75f0 100644
--- a/internal/bbsim/types/types.go
+++ b/internal/bbsim/types/types.go
@@ -20,7 +20,7 @@
"github.com/google/gopacket"
)
-// deprecated
+// deprecated, use OnuPacketOutMessage instead
type ByteMsg struct {
IntfId uint32
OnuId uint32
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index 8fe4ea8..4f222f2 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -31,7 +31,7 @@
)
const (
- DEFAULT_ONU_DEVICE_HEADER_FORMAT = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .SerialNumber }}\t{{ .STag }}\t{{ .CTag }}\t{{ .OperState }}\t{{ .InternalState }}"
+ DEFAULT_ONU_DEVICE_HEADER_FORMAT = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .PortNo }}\t{{ .SerialNumber }}\t{{ .STag }}\t{{ .CTag }}\t{{ .OperState }}\t{{ .InternalState }}"
)
type OnuSnString string