[SEBA-836] BBSim Reflector
Change-Id: Ib4ae5a2c24880dc62209bebb81188eca5f57865d
diff --git a/internal/bbsim/responders/dhcp/dhcp.go b/internal/bbsim/responders/dhcp/dhcp.go
index c7ae75c..25f5210 100644
--- a/internal/bbsim/responders/dhcp/dhcp.go
+++ b/internal/bbsim/responders/dhcp/dhcp.go
@@ -17,11 +17,13 @@
package dhcp
import (
+ "context"
"errors"
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/looplab/fsm"
+ "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
bbsim "github.com/opencord/bbsim/internal/bbsim/types"
omci "github.com/opencord/omci-sim"
"github.com/opencord/voltha-protos/go/openolt"
@@ -52,14 +54,14 @@
layers.DHCPOptNTPServers,
}
-func createDefaultDHCPReq(intfId uint32, onuId uint32) layers.DHCPv4 {
+func createDefaultDHCPReq(intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
return layers.DHCPv4{
Operation: layers.DHCPOpRequest,
HardwareType: layers.LinkTypeEthernet,
HardwareLen: 6,
HardwareOpts: 0,
Xid: onuId,
- ClientHWAddr: net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(intfId), byte(onuId)},
+ ClientHWAddr: mac,
}
}
@@ -85,8 +87,8 @@
return opts
}
-func createDHCPDisc(intfId uint32, onuId uint32) *layers.DHCPv4 {
- dhcpLayer := createDefaultDHCPReq(intfId, onuId)
+func createDHCPDisc(intfId uint32, onuId uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
+ dhcpLayer := createDefaultDHCPReq(intfId, onuId, macAddress)
defaultOpts := createDefaultOpts()
dhcpLayer.Options = append([]layers.DHCPOption{layers.DHCPOption{
Type: layers.DHCPOptMessageType,
@@ -94,11 +96,19 @@
Length: 1,
}}, defaultOpts...)
+ //data := []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
+ // 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
+ //dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
+ // Type: layers.DHCPOptClientID,
+ // Data: data,
+ // Length: uint8(len(data)),
+ //})
+
return &dhcpLayer
}
-func createDHCPReq(intfId uint32, onuId uint32) *layers.DHCPv4 {
- dhcpLayer := createDefaultDHCPReq(intfId, onuId)
+func createDHCPReq(intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
+ dhcpLayer := createDefaultDHCPReq(intfId, onuId, macAddress)
defaultOpts := createDefaultOpts()
dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
@@ -115,18 +125,18 @@
})
data = []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
- 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, 0xcb, 0xcc}
+ 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
Type: layers.DHCPOptClientID,
Data: data,
Length: uint8(len(data)),
})
- data = []byte{182, 21, 0, byte(onuId)}
+ // NOTE we should not request a specific IP, or we should request the one that has been offered
dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
Type: layers.DHCPOptRequestIP,
- Data: data,
- Length: uint8(len(data)),
+ Data: offeredIp,
+ Length: uint8(len(offeredIp)),
})
return &dhcpLayer
}
@@ -167,7 +177,7 @@
return bytes, nil
}
-func getDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
+func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
dhcp, _ := layerDHCP.(*layers.DHCPv4)
if dhcp == nil {
@@ -176,11 +186,15 @@
return dhcp, nil
}
-func getDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
+func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
for _, option := range dhcp.Options {
if option.Type == layers.DHCPOptMessageType {
- if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
+ if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
+ return layers.DHCPMsgTypeDiscover, nil
+ } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
return layers.DHCPMsgTypeOffer, nil
+ } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
+ return layers.DHCPMsgTypeRequest, nil
} else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
return layers.DHCPMsgTypeAck, nil
} else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
@@ -194,6 +208,20 @@
return 0, errors.New("Failed to extract MsgType from dhcp")
}
+// returns the DHCP Layer type or error if it's not a DHCP Packet
+func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
+ dhcpLayer, err := GetDhcpLayer(pkt)
+ if err != nil {
+ return "", err
+ }
+ dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
+ if err != nil {
+ return "", err
+ }
+
+ return dhcpMessageType.String(), nil
+}
+
func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, stream bbsim.Stream) error {
// FIXME unify sendDHCPPktIn and sendEapolPktIn methods
gemid, err := GetGemPortId(msg.IntfId, msg.OnuId)
@@ -219,8 +247,8 @@
return nil
}
-func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuHwAddress net.HardwareAddr, cTag int, stream openolt.Openolt_EnableIndicationServer) error {
- dhcp := createDHCPReq(ponPortId, onuId)
+func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuHwAddress net.HardwareAddr, offeredIp net.IP, stream openolt.Openolt_EnableIndicationServer) error {
+ dhcp := createDHCPReq(ponPortId, onuId, onuHwAddress, offeredIp)
pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
if err != nil {
@@ -239,11 +267,13 @@
if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
return err
}
+
dhcpLogger.WithFields(log.Fields{
- "OnuId": onuId,
- "IntfId": ponPortId,
- "OnuSn": serialNumber,
- }).Infof("DHCPDiscovery Sent")
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "OfferedIp": offeredIp.String(),
+ }).Infof("DHCPRequest Sent")
return nil
}
@@ -260,7 +290,7 @@
}
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)
+ dhcp := createDHCPDisc(ponPortId, onuId, onuHwAddress)
pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
if err != nil {
dhcpLogger.Errorf("Cannot serializeDHCPPacket: %s", err)
@@ -299,7 +329,7 @@
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)
+ dhcpLayer, err := GetDhcpLayer(pkt)
if err != nil {
dhcpLogger.WithFields(log.Fields{
"OnuId": onuId,
@@ -311,7 +341,7 @@
}
return err
}
- dhcpMessageType, err := getDhcpMessageType(dhcpLayer)
+ dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
if err != nil {
dhcpLogger.WithFields(log.Fields{
"OnuId": onuId,
@@ -326,7 +356,8 @@
if dhcpLayer.Operation == layers.DHCPOpReply {
if dhcpMessageType == layers.DHCPMsgTypeOffer {
- if err := sendDHCPRequest(ponPortId, onuId, serialNumber, portNo, onuHwAddress, cTag, stream); err != nil {
+ offeredIp := dhcpLayer.YourClientIP
+ if err := sendDHCPRequest(ponPortId, onuId, serialNumber, portNo, onuHwAddress, offeredIp, stream); err != nil {
dhcpLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -370,3 +401,94 @@
}
return nil
}
+
+// This method handle the BBR DHCP Packets
+// BBR does not need to do anything but forward the packets in the correct direction
+func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, sTag int, macAddress net.HardwareAddr, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
+
+ // check if the packet is going:
+ // - outgouing: toward the DHCP
+ // - incoming: toward the ONU
+ isIncoming := packetHandlers.IsIncomingPacket(pkt)
+ log.Tracef("Is Incoming: %t", isIncoming)
+
+ dhcpType, err := GetDhcpPacketType(pkt)
+ if err != nil {
+ log.WithFields(log.Fields{
+ "err": err,
+ }).Fatalf("Can't find DHCP type for packet")
+ }
+
+ srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
+ dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
+
+ if isIncoming == true {
+
+ onuPacket := openolt.OnuPacket{
+ IntfId: ponPortId,
+ OnuId: onuId,
+ PortNo: onuId,
+ GemportId: 1,
+ Pkt: pkt.Data(),
+ }
+
+ if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "Type": dhcpType,
+ "error": err,
+ }).Error("Failed to send DHCP packet to the ONU")
+ }
+
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "Type": dhcpType,
+ "DstMac": dstMac,
+ "SrcMac": srcMac,
+ "OnuMac": macAddress,
+ }).Infof("Sent DHCP packet to the ONU")
+
+ // TODO: signal that the ONU has completed
+ dhcpLayer, _ := GetDhcpLayer(pkt)
+ dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
+ if dhcpMessageType == layers.DHCPMsgTypeAck {
+ doneChannel <- true
+ }
+
+ } else {
+ // double tag the packet and send it to the NNI
+ // NOTE do we need this in the HandleDHCP Packet?
+ doubleTaggedPkt, err := packetHandlers.PushDoubleTag(sTag, sTag, pkt)
+ if err != nil {
+ log.Error("Failt to add double tag to packet")
+ }
+
+ pkt := openolt.UplinkPacket{
+ IntfId: 0, // BBSim does not care about which NNI, it has only one
+ Pkt: doubleTaggedPkt.Data(),
+ }
+ if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "Type": dhcpType,
+ "error": err,
+ }).Error("Failed to send DHCP packet out of the NNI Port")
+ }
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "Type": dhcpType,
+ "DstMac": dstMac,
+ "SrcMac": srcMac,
+ "OnuMac": macAddress,
+ }).Infof("Sent DHCP packet out of the NNI Port")
+ }
+ return nil
+}