[SEBA-918][VOL-2984] Allowing DHCP without completing eapol
For DT and TT workflow is required that DHCP is triggered without doing
anything for EAPOL. If you start BBSim with only the "-dhcp" option that
is now possible.
Change-Id: Iacfb75e70c47a2f7cfa64af58d6d848881f54974
diff --git a/internal/bbsim/devices/onu_flow_test.go b/internal/bbsim/devices/onu_flow_test.go
index e8fa451..9ab8abb 100644
--- a/internal/bbsim/devices/onu_flow_test.go
+++ b/internal/bbsim/devices/onu_flow_test.go
@@ -21,7 +21,9 @@
"github.com/looplab/fsm"
"github.com/opencord/voltha-protos/v2/go/openolt"
"gotest.tools/assert"
+ "sync"
"testing"
+ "time"
)
func Test_Onu_SendEapolFlow(t *testing.T) {
@@ -46,15 +48,16 @@
}
// validates that when an ONU receives an EAPOL flow for UNI 0
+// and the GemPort has already been configured
// it transition to auth_started state
-func Test_HandleFlowUpdateEapolFromGem(t *testing.T) {
+func Test_HandleFlowUpdateEapolWithGem(t *testing.T) {
onu := createMockOnu(1, 1, 900, 900, true, false)
onu.InternalState = fsm.NewFSM(
- "gem_port_added",
+ "enabled",
fsm.Events{
- {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
+ {Name: "start_auth", Src: []string{"enabled"}, Dst: "auth_started"},
},
fsm.Callbacks{},
)
@@ -87,97 +90,15 @@
}
// validates that when an ONU receives an EAPOL flow for UNI that is not 0
-// no action is taken
-func Test_HandleFlowUpdateEapolFromGemIgnore(t *testing.T) {
+// no action is taken (this is independent of GemPort status
+func Test_HandleFlowUpdateEapolWrongUNI(t *testing.T) {
- onu := createMockOnu(1, 1, 900, 900, false, false)
-
- onu.InternalState = fsm.NewFSM(
- "gem_port_added",
- fsm.Events{
- {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
- },
- fsm.Callbacks{},
- )
-
- flow := openolt.Flow{
- AccessIntfId: int32(onu.PonPortID),
- OnuId: int32(onu.ID),
- UniId: int32(1),
- FlowId: uint32(onu.ID),
- FlowType: "downstream",
- AllocId: int32(0),
- NetworkIntfId: int32(0),
- Classifier: &openolt.Classifier{
- EthType: uint32(layers.EthernetTypeEAPOL),
- OVid: 4091,
- },
- Action: &openolt.Action{},
- Priority: int32(100),
- PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
- }
-
- msg := OnuFlowUpdateMessage{
- PonPortID: 1,
- OnuID: 1,
- Flow: &flow,
- }
-
- onu.handleFlowUpdate(msg)
- assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
-}
-
-// validates that when an ONU receives an EAPOL flow for UNI 0
-// it transition to auth_started state
-func Test_HandleFlowUpdateEapolFromEnabled(t *testing.T) {
-
- onu := createMockOnu(1, 1, 900, 900, false, false)
+ onu := createMockOnu(1, 1, 900, 900, true, false)
onu.InternalState = fsm.NewFSM(
"enabled",
fsm.Events{
- {Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
- },
- fsm.Callbacks{},
- )
-
- flow := openolt.Flow{
- AccessIntfId: int32(onu.PonPortID),
- OnuId: int32(onu.ID),
- UniId: int32(0),
- FlowId: uint32(onu.ID),
- FlowType: "downstream",
- AllocId: int32(0),
- NetworkIntfId: int32(0),
- Classifier: &openolt.Classifier{
- EthType: uint32(layers.EthernetTypeEAPOL),
- OVid: 4091,
- },
- Action: &openolt.Action{},
- Priority: int32(100),
- PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
- }
-
- msg := OnuFlowUpdateMessage{
- PonPortID: 1,
- OnuID: 1,
- Flow: &flow,
- }
-
- onu.handleFlowUpdate(msg)
- assert.Equal(t, onu.InternalState.Current(), "eapol_flow_received")
-}
-
-// validates that when an ONU receives an EAPOL flow for UNI that is not 0
-// no action is taken
-func Test_HandleFlowUpdateEapolFromEnabledIgnore(t *testing.T) {
-
- onu := createMockOnu(1, 1, 900, 900, false, false)
-
- onu.InternalState = fsm.NewFSM(
- "enabled",
- fsm.Events{
- {Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
+ {Name: "start_auth", Src: []string{"enabled"}, Dst: "auth_started"},
},
fsm.Callbacks{},
)
@@ -210,14 +131,17 @@
}
// validates that when an ONU receives an EAPOL flow for UNI 0
-// but the noAuth bit is set no action is taken
-func Test_HandleFlowUpdateEapolNoAuth(t *testing.T) {
- onu := createMockOnu(1, 1, 900, 900, false, false)
+// and the GemPort has not yet been configured
+// it transition to auth_started state
+func Test_HandleFlowUpdateEapolWithoutGem(t *testing.T) {
+
+ onu := createMockOnu(1, 1, 900, 900, true, false)
+ onu.GemPortAdded = false
onu.InternalState = fsm.NewFSM(
- "gem_port_added",
+ "enabled",
fsm.Events{
- {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
+ {Name: "start_auth", Src: []string{"enabled"}, Dst: "auth_started"},
},
fsm.Callbacks{},
)
@@ -246,9 +170,68 @@
}
onu.handleFlowUpdate(msg)
- assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
+
+ wg := sync.WaitGroup{}
+ wg.Add(1)
+ go func(wg *sync.WaitGroup) {
+ defer wg.Done()
+ time.Sleep(100 * time.Millisecond)
+
+ // emulate the addition of a GemPort
+ for _, ch := range onu.GemPortChannels {
+ ch <- true
+ }
+
+ time.Sleep(100 * time.Millisecond)
+ assert.Equal(t, onu.InternalState.Current(), "auth_started")
+ }(&wg)
+ wg.Wait()
+
}
+// validates that when an ONU receives an EAPOL flow for UNI 0
+// but the noAuth bit is set no action is taken
+func Test_HandleFlowUpdateEapolNoAuth(t *testing.T) {
+ onu := createMockOnu(1, 1, 900, 900, false, false)
+
+ onu.InternalState = fsm.NewFSM(
+ "enabled",
+ fsm.Events{
+ {Name: "start_auth", Src: []string{"enabled"}, Dst: "auth_started"},
+ },
+ fsm.Callbacks{},
+ )
+
+ flow := openolt.Flow{
+ AccessIntfId: int32(onu.PonPortID),
+ OnuId: int32(onu.ID),
+ UniId: int32(0),
+ FlowId: uint32(onu.ID),
+ FlowType: "downstream",
+ AllocId: int32(0),
+ NetworkIntfId: int32(0),
+ Classifier: &openolt.Classifier{
+ EthType: uint32(layers.EthernetTypeEAPOL),
+ OVid: 4091,
+ },
+ Action: &openolt.Action{},
+ Priority: int32(100),
+ PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
+ }
+
+ msg := OnuFlowUpdateMessage{
+ PonPortID: 1,
+ OnuID: 1,
+ Flow: &flow,
+ }
+
+ onu.handleFlowUpdate(msg)
+ assert.Equal(t, onu.InternalState.Current(), "enabled")
+}
+
+// validates that when an ONU receives a DHCP flow for UNI 0 and pbit 0
+// and the GemPort has already been configured
+// it transition to dhcp_started state
func Test_HandleFlowUpdateDhcp(t *testing.T) {
onu := createMockOnu(1, 1, 900, 900, false, true)
@@ -272,7 +255,7 @@
EthType: uint32(layers.EthernetTypeIPv4),
SrcPort: uint32(68),
DstPort: uint32(67),
- OPbits: 0,
+ OPbits: 0,
},
Action: &openolt.Action{},
Priority: int32(100),
@@ -290,6 +273,9 @@
assert.Equal(t, onu.DhcpFlowReceived, true)
}
+// validates that when an ONU receives a DHCP flow for UNI 0 and pbit 255
+// and the GemPort has already been configured
+// it transition to dhcp_started state
func Test_HandleFlowUpdateDhcpPBit255(t *testing.T) {
onu := createMockOnu(1, 1, 900, 900, false, true)
@@ -313,7 +299,7 @@
EthType: uint32(layers.EthernetTypeIPv4),
SrcPort: uint32(68),
DstPort: uint32(67),
- OPbits: 0,
+ OPbits: 255,
},
Action: &openolt.Action{},
Priority: int32(100),
@@ -331,6 +317,9 @@
assert.Equal(t, onu.DhcpFlowReceived, true)
}
+// validates that when an ONU receives a DHCP flow for UNI 0 and pbit not 0 or 255
+// and the GemPort has already been configured
+// it ignores the message
func Test_HandleFlowUpdateDhcpIgnoreByPbit(t *testing.T) {
onu := createMockOnu(1, 1, 900, 900, false, true)
@@ -354,7 +343,7 @@
EthType: uint32(layers.EthernetTypeIPv4),
SrcPort: uint32(68),
DstPort: uint32(67),
- OPbits: 1,
+ OPbits: 1,
},
Action: &openolt.Action{},
Priority: int32(100),
@@ -372,6 +361,8 @@
assert.Equal(t, onu.DhcpFlowReceived, false)
}
+// validates that when an ONU receives a DHCP flow for UNI 0
+// but the noDchp bit is set no action is taken
func Test_HandleFlowUpdateDhcpNoDhcp(t *testing.T) {
onu := createMockOnu(1, 1, 900, 900, false, false)
@@ -411,3 +402,66 @@
assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
assert.Equal(t, onu.DhcpFlowReceived, false)
}
+
+// validates that when an ONU receives a DHCP flow for UNI 0 and pbit not 0 or 255
+// and the GemPort has not already been configured
+// it transition to dhcp_started state
+func Test_HandleFlowUpdateDhcpWithoutGem(t *testing.T) {
+ // NOTE that this feature is required when we do DHCP with no eapol
+ // as the DHCP flow will be the first one received
+ onu := createMockOnu(1, 1, 900, 900, false, true)
+
+ onu.GemPortAdded = false
+
+ onu.InternalState = fsm.NewFSM(
+ "enabled",
+ fsm.Events{
+ {Name: "start_dhcp", Src: []string{"enabled"}, Dst: "dhcp_started"},
+ },
+ fsm.Callbacks{},
+ )
+
+ flow := openolt.Flow{
+ AccessIntfId: int32(onu.PonPortID),
+ OnuId: int32(onu.ID),
+ UniId: int32(0),
+ FlowId: uint32(onu.ID),
+ FlowType: "downstream",
+ AllocId: int32(0),
+ NetworkIntfId: int32(0),
+ Classifier: &openolt.Classifier{
+ EthType: uint32(layers.EthernetTypeIPv4),
+ SrcPort: uint32(68),
+ DstPort: uint32(67),
+ OPbits: 0,
+ },
+ Action: &openolt.Action{},
+ Priority: int32(100),
+ PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
+ }
+
+ msg := OnuFlowUpdateMessage{
+ PonPortID: 1,
+ OnuID: 1,
+ Flow: &flow,
+ }
+
+ onu.handleFlowUpdate(msg)
+
+ wg := sync.WaitGroup{}
+ wg.Add(1)
+ go func(wg *sync.WaitGroup) {
+ defer wg.Done()
+ time.Sleep(100 * time.Millisecond)
+
+ // emulate the addition of a GemPort
+ for _, ch := range onu.GemPortChannels {
+ ch <- true
+ }
+
+ time.Sleep(100 * time.Millisecond)
+ assert.Equal(t, onu.InternalState.Current(), "dhcp_started")
+ assert.Equal(t, onu.DhcpFlowReceived, true)
+ }(&wg)
+ wg.Wait()
+}