Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions layers/sflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,11 @@ func decodeFlowSample(data *[]byte, expanded bool) (SFlowFlowSample, error) {
return s, err
}
case SFlowTypeEthernetFrameFlow:
// TODO
skipRecord(data)
return s, errors.New("skipping TypeEthernetFrameFlow")
if record, err := decodeSFlowEthernetFrameRecord(data); err == nil {
s.Records = append(s.Records, record)
} else {
return s, err
}
case SFlowTypeIpv4Flow:
if record, err := decodeSFlowIpv4Record(data); err == nil {
s.Records = append(s.Records, record)
Expand Down Expand Up @@ -1613,6 +1615,7 @@ func decodeExtendedUserFlow(data *[]byte) (SFlowExtendedUserFlow, error) {
// | TOS |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
type SFlowIpv4Record struct {
SFlowBaseFlowRecord
// The length of the IP packet excluding ower layer encapsulations
Length uint32
// IP Protocol type (for example, TCP = 6, UDP = 17)
Expand All @@ -1633,6 +1636,11 @@ type SFlowIpv4Record struct {

func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
si := SFlowIpv4Record{}
var ir SFlowFlowDataFormat

*data, ir = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did test it and it seems to be not working for tunneling record. I tested it with Openswitch. Did you see any issue with tunneling record or was it with another kind of record ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safchain, do you have a test case that could be added to the tests in this pull?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gconnell there is already a test that this PR modifies. According to my test with Openvswitch, it doesn't seem to be working properly with this patch.

@lflxp Maybe the IPV4/IPV6 records are used somewhere else by sFlow protocol needing SFlowBaseFlowRecord. In that case we will need to use a king of decodeSFlowIpv4Data used by decodeSFlowIpv4Record and decodeExtendedIpv4TunnelEgress.

Below two records from a lab, first one without the patch second one with it. In the second one the SFlowIpv4Record is incorrect.

{SFlowBaseFlowRecord:{EnterpriseID:Standard SFlow Format:Extended IPv4 Tunnel Ingress Record FlowDataLength:32} SFlowIpv4Record:{Length:0 Protocol:47 IPSrc:10.41.20.10 IPDst:10.41.20.14 PortSrc:0 PortDst:0 TCPFlags:0 TOS:0}}

{SFlowBaseFlowRecord:{EnterpriseID:Standard SFlow Format:Extended IPv4 Tunnel Ingress Record FlowDataLength:32} SFlowIpv4Record:{SFlowBaseFlowRecord:{EnterpriseID:Standard SFlow Format: FlowDataLength:47} Length:170464266 Protocol:170464270 IPSrc:0.0.0.0 IPDst:0.0.0.0 PortSrc:0 PortDst:0 TCPFlags:3 TOS:1001}}

si.EnterpriseID, si.Format = ir.decode()
*data, si.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])

*data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
*data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
Expand Down Expand Up @@ -1669,6 +1677,7 @@ func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
// | Priority |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
type SFlowIpv6Record struct {
SFlowBaseFlowRecord
// The length of the IP packet excluding ower layer encapsulations
Length uint32
// IP Protocol type (for example, TCP = 6, UDP = 17)
Expand All @@ -1689,6 +1698,11 @@ type SFlowIpv6Record struct {

func decodeSFlowIpv6Record(data *[]byte) (SFlowIpv6Record, error) {
si := SFlowIpv6Record{}
var ir SFlowFlowDataFormat

*data, ir = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
si.EnterpriseID, si.Format = ir.decode()
*data, si.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])

*data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
*data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
Expand Down Expand Up @@ -1938,6 +1952,55 @@ func decodeExtendedVniIngress(data *[]byte) (SFlowExtendedVniIngressRecord, erro
return rec, nil
}

// **************************************************
// Packet Ethernet Data Record
// **************************************************

// 0 15 31
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | Length |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | |
// | Src Mac |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | |
// | Dst Mac |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | Type |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | Src Mac | Dst Mac |
// +--+--+--+--+--+--+--+--+
type SFlowEthernetFrameRecord struct {
SFlowBaseFlowRecord
//为2代表是Ethernet Frame Data字段
Length_mac uint32
//源mac地址8字节
SrcMac []byte
//目的mac地址8字节
DstMac []byte
Type uint32
}

func decodeSFlowEthernetFrameRecord(data *[]byte) (SFlowEthernetFrameRecord, error) {
sef := SFlowEthernetFrameRecord{}
var efr SFlowFlowDataFormat

*data, efr = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
sef.EnterpriseID, sef.Format = efr.decode()
//fmt.Println("=============start================decodeSFlowEthernetFrameRecord")
*data, sef.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
*data, sef.Length_mac = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
//fmt.Println("decodeSFlowEthernetFrameRecord Format",sef.Format,*data)
*data, sef.SrcMac = (*data)[8:], (*data)[:8]
//fmt.Println("decodeSFlowEthernetFrameRecord SrcMac",string(sef.SrcMac),*data)
*data, sef.DstMac = (*data)[8:], (*data)[:8]
//fmt.Println("decodeSFlowEthernetFrameRecord DstMac",string(sef.DstMac),*data)
*data, sef.Type = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
//fmt.Println("decodeSFlowEthernetFrameRecord Format",sef.Type,*data)

return sef, nil
}

// **************************************************
// Counter Record
// **************************************************
Expand Down
8 changes: 7 additions & 1 deletion layers/sflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
package layers

import (
"github.com/google/gopacket"
"net"
"reflect"
"testing"

"github.com/google/gopacket"
)

// Test packet collected from live network. See the test below for contents
Expand Down Expand Up @@ -1129,6 +1130,11 @@ func TestDecodeExtendedIpv4TunnelIngressFlow(t *testing.T) {
FlowDataLength: 0x20,
},
SFlowIpv4Record: SFlowIpv4Record{
SFlowBaseFlowRecord: SFlowBaseFlowRecord{
EnterpriseID: 0x0,
Format: SFlowTypeIpv4Flow,
FlowDataLength: 0x20,
},
Length: 0x0,
Protocol: 0x2f,
IPSrc: net.IP{0xc0, 0xa8, 0x0, 0x54},
Expand Down