diff --git a/cmd/collector/collector.go b/cmd/collector/collector.go index 7fc39a88..5f5d72ca 100644 --- a/cmd/collector/collector.go +++ b/cmd/collector/collector.go @@ -87,7 +87,6 @@ func printIPFIXMessage(msg *entities.Message) { case entities.Unsigned8: fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetUnsigned8Value()) case entities.Unsigned16: - fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetUnsigned16Value()) case entities.Unsigned32: fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetUnsigned32Value()) @@ -107,13 +106,8 @@ func printIPFIXMessage(msg *entities.Message) { fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetFloat64Value()) case entities.Boolean: fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetBooleanValue()) - case entities.DateTimeSeconds: - fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetUnsigned32Value()) - case entities.DateTimeMilliseconds: - fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetUnsigned64Value()) - case entities.DateTimeMicroseconds, entities.DateTimeNanoseconds: - err := fmt.Errorf("API does not support micro and nano seconds types yet") - fmt.Fprintf(&buf, " %s: %v \n", elem.Name, err) + case entities.DateTimeSeconds, entities.DateTimeMilliseconds, entities.DateTimeMicroseconds, entities.DateTimeNanoseconds: + fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetDateTimeValue()) case entities.MacAddress: fmt.Fprintf(&buf, " %s: %v \n", elem.Name, ie.GetMacAddressValue()) case entities.Ipv4Address, entities.Ipv6Address: diff --git a/pkg/entities/ie.go b/pkg/entities/ie.go index de72b331..a6562fc1 100644 --- a/pkg/entities/ie.go +++ b/pkg/entities/ie.go @@ -19,6 +19,7 @@ import ( "fmt" "math" "net" + "time" ) type IEDataType uint8 @@ -189,13 +190,12 @@ func decodeToIEDataType(dataType IEDataType, val interface{}) (interface{}, erro return false, nil } case DateTimeSeconds: - v := binary.BigEndian.Uint32(value) - return v, nil + return time.Unix(int64(binary.BigEndian.Uint32(value)), 0), nil case DateTimeMilliseconds: v := binary.BigEndian.Uint64(value) - return v, nil + return time.Unix(int64(v/1000), int64(v%1000)*1000000), nil case DateTimeMicroseconds, DateTimeNanoseconds: - return nil, fmt.Errorf("API does not support micro and nano seconds types yet") + return ntpTime(binary.BigEndian.Uint64(value)).Time(), nil case MacAddress: return net.HardwareAddr(value), nil case Ipv4Address, Ipv6Address: @@ -300,23 +300,25 @@ func DecodeAndCreateInfoElementWithValue(element *InfoElement, value []byte) (In return NewBoolInfoElement(element, false), nil } case DateTimeSeconds: - var val uint32 - if value == nil { - val = 0 - } else { - val = binary.BigEndian.Uint32(value) + var val time.Time + if value != nil { + val = time.Unix(int64(binary.BigEndian.Uint32(value)), 0) } - return NewDateTimeSecondsInfoElement(element, val), nil + return NewDateTimeInfoElement(element, val), nil case DateTimeMilliseconds: - var val uint64 - if value == nil { - val = 0 - } else { - val = binary.BigEndian.Uint64(value) + var val time.Time + if value != nil { + v := binary.BigEndian.Uint64(value) + val = time.Unix(int64(v/1000), int64(v%1000)*1000000) } - return NewDateTimeMillisecondsInfoElement(element, val), nil + return NewDateTimeInfoElement(element, val), nil case DateTimeMicroseconds, DateTimeNanoseconds: - return nil, fmt.Errorf("API does not support micro and nano seconds types yet") + var val time.Time + if value != nil { + v := binary.BigEndian.Uint64(value) + val = ntpTime(v).Time() + } + return NewDateTimeInfoElement(element, val), nil case MacAddress: return NewMacAddressInfoElement(element, value), nil case Ipv4Address, Ipv6Address: @@ -428,25 +430,37 @@ func EncodeToIEDataType(dataType IEDataType, val interface{}) ([]byte, error) { } return b, nil case DateTimeSeconds: - v, ok := val.(uint32) + v, ok := val.(time.Time) if !ok { - return nil, fmt.Errorf("val argument %v is not of type uint32", val) + return nil, fmt.Errorf("val argument %v is not of type Time", val) } b := make([]byte, 4) - binary.BigEndian.PutUint32(b, v) + binary.BigEndian.PutUint32(b, uint32(v.Unix())) return b, nil case DateTimeMilliseconds: - v, ok := val.(uint64) + v, ok := val.(time.Time) if !ok { - return nil, fmt.Errorf("val argument %v is not of type uint64", val) + return nil, fmt.Errorf("val argument %v is not of type Time", val) } b := make([]byte, 8) - binary.BigEndian.PutUint64(b, v) + binary.BigEndian.PutUint64(b, uint64(v.UnixNano()/1000000)) + return b, nil + case DateTimeMicroseconds: + v, ok := val.(time.Time) + if !ok { + return nil, fmt.Errorf("val argument %v is not of type Time", val) + } + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(toNtpTime(v.Truncate(time.Microsecond)))) + return b, nil + case DateTimeNanoseconds: + v, ok := val.(time.Time) + if !ok { + return nil, fmt.Errorf("val argument %v is not of type Time", val) + } + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(toNtpTime(v))) return b, nil - // Currently only supporting seconds and milliseconds - case DateTimeMicroseconds, DateTimeNanoseconds: - // TODO: RFC 7011 has extra spec for these data types. Need to follow that - return nil, fmt.Errorf("API does not support micro and nano seconds types yet") case MacAddress: // Expects net.Hardware type v, ok := val.(net.HardwareAddr) @@ -535,13 +549,13 @@ func encodeInfoElementValueToBuff(element InfoElementWithValue, buffer []byte, i } copy(buffer[index:index+1], []byte{indicator}) case DateTimeSeconds: - binary.BigEndian.PutUint32(buffer[index:], element.GetUnsigned32Value()) + binary.BigEndian.PutUint32(buffer[index:], uint32(element.GetDateTimeValue().Unix())) case DateTimeMilliseconds: - binary.BigEndian.PutUint64(buffer[index:], element.GetUnsigned64Value()) - // Currently only supporting seconds and milliseconds - case DateTimeMicroseconds, DateTimeNanoseconds: - // TODO: RFC 7011 has extra spec for these data types. Need to follow that - return fmt.Errorf("API does not support micro and nano seconds types yet") + binary.BigEndian.PutUint64(buffer[index:], uint64(element.GetDateTimeValue().UnixNano()/1000000)) + case DateTimeMicroseconds: + binary.BigEndian.PutUint64(buffer[index:], uint64(toNtpTime(element.GetDateTimeValue().Truncate(time.Microsecond)))) + case DateTimeNanoseconds: + binary.BigEndian.PutUint64(buffer[index:], uint64(toNtpTime(element.GetDateTimeValue()))) case MacAddress: copy(buffer[index:], element.GetMacAddressValue()) case Ipv4Address: diff --git a/pkg/entities/ie_test.go b/pkg/entities/ie_test.go index 9f95355e..59eadcef 100644 --- a/pkg/entities/ie_test.go +++ b/pkg/entities/ie_test.go @@ -3,6 +3,7 @@ package entities import ( "net" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -28,7 +29,10 @@ var valData = []struct { {true, 1, Boolean, true, []byte{0x1}}, {false, 1, Boolean, false, []byte{0x2}}, {macAddress, 6, MacAddress, net.HardwareAddr([]byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}), []byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, - {uint32(1257894000), 4, DateTimeSeconds, uint32(1257894000), []byte{0x4a, 0xf9, 0xf0, 0x70}}, + {time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).In(time.Local), 4, DateTimeSeconds, time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).In(time.Local), []byte{0x4a, 0xf9, 0xf0, 0x70}}, + {time.Date(2009, time.November, 10, 23, 0, 0, 42000000, time.UTC).In(time.Local), 8, DateTimeMilliseconds, time.Date(2009, time.November, 10, 23, 0, 0, 42000000, time.UTC).In(time.Local), []byte{0x00, 0x00, 0x01, 0x24, 0xe0, 0x53, 0x35, 0xaa}}, + {time.Date(2022, time.February, 21, 16, 59, 56, 141509000, time.UTC).In(time.Local), 8, DateTimeMicroseconds, time.Date(2022, time.February, 21, 16, 59, 56, 141509000, time.UTC).In(time.Local), []byte{0xe5, 0xbe, 0x43, 0x8c, 0x24, 0x39, 0xef, 0x0f}}, + {time.Date(2022, time.February, 21, 16, 59, 56, 141509436, time.UTC).In(time.Local), 8, DateTimeNanoseconds, time.Date(2022, time.February, 21, 16, 59, 56, 141509436, time.UTC).In(time.Local), []byte{0xe5, 0xbe, 0x43, 0x8c, 0x24, 0x39, 0xf6, 0x60}}, {net.ParseIP("1.2.3.4"), 4, Ipv4Address, net.IP([]byte{0x1, 0x2, 0x3, 0x4}), []byte{0x1, 0x2, 0x3, 0x4}}, {net.ParseIP("2001:0:3238:DFE1:63::FEFB"), 16, Ipv6Address, net.IP([]byte{0x20, 0x1, 0x0, 0x0, 0x32, 0x38, 0xdf, 0xe1, 0x0, 0x63, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xfb}), []byte{0x20, 0x1, 0x0, 0x0, 0x32, 0x38, 0xdf, 0xe1, 0x0, 0x63, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xfb}}, } @@ -37,6 +41,7 @@ func TestDecodeToIEDataType(t *testing.T) { for _, data := range valData { buff, err := EncodeToIEDataType(data.dataType, data.value) assert.Nil(t, err) + assert.Equal(t, data.length, len(buff)) v, err := decodeToIEDataType(data.dataType, buff) assert.Nil(t, err) assert.Equal(t, data.expectedDecode, v) diff --git a/pkg/entities/ie_value.go b/pkg/entities/ie_value.go index 1d240f69..ba6afc06 100644 --- a/pkg/entities/ie_value.go +++ b/pkg/entities/ie_value.go @@ -2,6 +2,7 @@ package entities import ( "net" + "time" ) type InfoElementWithValue interface { @@ -25,6 +26,7 @@ type InfoElementWithValue interface { GetMacAddressValue() net.HardwareAddr GetStringValue() string GetIPAddressValue() net.IP + GetDateTimeValue() time.Time SetUnsigned8Value(val uint8) SetUnsigned16Value(val uint16) SetUnsigned32Value(val uint32) @@ -39,6 +41,7 @@ type InfoElementWithValue interface { SetMacAddressValue(val net.HardwareAddr) SetStringValue(val string) SetIPAddressValue(val net.IP) + SetDateTimeValue(val time.Time) IsValueEmpty() bool GetLength() int ResetValue() @@ -120,6 +123,10 @@ func (b *baseInfoElement) GetIPAddressValue() net.IP { panic("accessing value of wrong data type") } +func (b *baseInfoElement) GetDateTimeValue() time.Time { + panic("accessing value of wrong data type") +} + func (b *baseInfoElement) SetUnsigned8Value(val uint8) { panic("setting value with wrong data type") } @@ -176,6 +183,10 @@ func (b *baseInfoElement) SetIPAddressValue(val net.IP) { panic("setting value with wrong data type") } +func (b *baseInfoElement) SetDateTimeValue(val time.Time) { + panic("setting value with wrong data type") +} + func (b *baseInfoElement) GetLength() int { return int(b.element.Len) } @@ -566,62 +577,33 @@ func (s *StringInfoElement) ResetValue() { s.value = "" } -type DateTimeSecondsInfoElement struct { - value uint32 - baseInfoElement -} - -func NewDateTimeSecondsInfoElement(element *InfoElement, val uint32) *DateTimeSecondsInfoElement { - infoElem := &DateTimeSecondsInfoElement{ - value: val, - } - infoElem.element = element - return infoElem -} - -func (dsec *DateTimeSecondsInfoElement) GetUnsigned32Value() uint32 { - return dsec.value -} - -func (dsec *DateTimeSecondsInfoElement) SetUnsigned32Value(val uint32) { - dsec.value = val -} - -func (dsec *DateTimeSecondsInfoElement) IsValueEmpty() bool { - return dsec.value == 0 -} - -func (dsec *DateTimeSecondsInfoElement) ResetValue() { - dsec.value = 0 -} - -type DateTimeMillisecondsInfoElement struct { - value uint64 +type DateTimeInfoElement struct { + value time.Time baseInfoElement } -func NewDateTimeMillisecondsInfoElement(element *InfoElement, val uint64) *DateTimeMillisecondsInfoElement { - infoElem := &DateTimeMillisecondsInfoElement{ +func NewDateTimeInfoElement(element *InfoElement, val time.Time) *DateTimeInfoElement { + infoElem := &DateTimeInfoElement{ value: val, } infoElem.element = element return infoElem } -func (dmsec *DateTimeMillisecondsInfoElement) GetUnsigned64Value() uint64 { +func (dmsec *DateTimeInfoElement) GetDateTimeValue() time.Time { return dmsec.value } -func (dmsec *DateTimeMillisecondsInfoElement) SetUnsigned64Value(val uint64) { +func (dmsec *DateTimeInfoElement) SetDateTimeValue(val time.Time) { dmsec.value = val } -func (dmsec *DateTimeMillisecondsInfoElement) IsValueEmpty() bool { - return dmsec.value == 0 +func (dmsec *DateTimeInfoElement) IsValueEmpty() bool { + return dmsec.value == time.Time{} } -func (dmsec *DateTimeMillisecondsInfoElement) ResetValue() { - dmsec.value = 0 +func (dmsec *DateTimeInfoElement) ResetValue() { + dmsec.value = time.Time{} } type IPAddressInfoElement struct { diff --git a/pkg/entities/ntptime.go b/pkg/entities/ntptime.go new file mode 100644 index 00000000..67b4a722 --- /dev/null +++ b/pkg/entities/ntptime.go @@ -0,0 +1,53 @@ +// Based on https://github.com/beevik/ntp/blob/master/ntp.go +// Original copyright follows + +// Copyright 2015-2017 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package entities + +import "time" + +const ( + nanoPerSec = 1000000000 +) + +var ( + ntpEpoch = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC) +) + +// An ntpTime is a 64-bit fixed-point (Q32.32) representation of the number of +// seconds elapsed. +type ntpTime uint64 + +// Duration interprets the fixed-point ntpTime as a number of elapsed seconds +// and returns the corresponding time.Duration value. +func (t ntpTime) Duration() time.Duration { + sec := (t >> 32) * nanoPerSec + frac := (t & 0xffffffff) * nanoPerSec + nsec := frac >> 32 + if uint32(frac) >= 0x80000000 { + nsec++ + } + return time.Duration(sec + nsec) +} + +// Time interprets the fixed-point ntpTime as an absolute time and returns +// the corresponding time.Time value. +func (t ntpTime) Time() time.Time { + return ntpEpoch.Add(t.Duration()).In(time.Local) +} + +// toNtpTime converts the time.Time value t into its 64-bit fixed-point +// ntpTime representation. +func toNtpTime(t time.Time) ntpTime { + nsec := uint64(t.Sub(ntpEpoch)) + sec := nsec / nanoPerSec + nsec = uint64(nsec-sec*nanoPerSec) << 32 + frac := uint64(nsec / nanoPerSec) + if nsec%nanoPerSec >= nanoPerSec/2 { + frac++ + } + return ntpTime(sec<<32 | frac) +} diff --git a/pkg/entities/record.go b/pkg/entities/record.go index 43544bec..2b2fc738 100644 --- a/pkg/entities/record.go +++ b/pkg/entities/record.go @@ -139,13 +139,8 @@ func (b *baseRecord) GetElementMap() map[string]interface{} { elements[element.GetName()] = element.GetFloat64Value() case Boolean: elements[element.GetName()] = element.GetBooleanValue() - case DateTimeSeconds: - elements[element.GetName()] = element.GetUnsigned32Value() - case DateTimeMilliseconds: - elements[element.GetName()] = element.GetUnsigned64Value() - case DateTimeMicroseconds, DateTimeNanoseconds: - err := fmt.Errorf("API does not support micro and nano seconds types yet") - elements[element.GetName()] = err + case DateTimeSeconds, DateTimeMilliseconds, DateTimeMicroseconds, DateTimeNanoseconds: + elements[element.GetName()] = element.GetDateTimeValue() case MacAddress: elements[element.GetName()] = element.GetMacAddressValue() case Ipv4Address, Ipv6Address: diff --git a/pkg/entities/record_test.go b/pkg/entities/record_test.go index f9471161..fa694181 100644 --- a/pkg/entities/record_test.go +++ b/pkg/entities/record_test.go @@ -59,6 +59,8 @@ func TestAddInfoElements(t *testing.T) { NewInfoElement("interfaceDescription", 83, 13, 0, 65535), // String NewInfoElement("flowStartSeconds", 150, 14, 0, 4), // dateTimeSeconds NewInfoElement("flowStartMilliseconds", 152, 15, 0, 8), // dateTimeMilliseconds + NewInfoElement("flowStartMicroseconds", 154, 16, 0, 8), // dateTimeMicroseconds + NewInfoElement("flowStartNanoseconds", 156, 17, 0, 8), // dateTimeNanoseconds } macAddress, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff") type valData struct { @@ -72,8 +74,10 @@ func TestAddInfoElements(t *testing.T) { macAddr net.HardwareAddr ipAddr net.IP stringVal string - flowStartSecs uint32 - flowStartMillisecs uint64 + flowStartSecs time.Time + flowStartMillisecs time.Time + flowStartMicrosecs time.Time + flowStartNanosecs time.Time } values := valData{ uint8(0x1), // ICMP proto @@ -86,15 +90,17 @@ func TestAddInfoElements(t *testing.T) { macAddress, // mac address net.ParseIP("1.2.3.4"), // IP Address "My Interface in IPFIX lib", // String - uint32(time.Now().Unix()), // dateTimeSeconds - uint64(time.Now().Unix()), // dateTimeMilliseconds + time.Now(), // dateTimeSeconds + time.Now(), // dateTimeMilliseconds + time.Now(), // dateTimeMicroseconds + time.Now(), // dateTimeNanoseconds } addIETests := []struct { record Record ieList []*InfoElement valList valData }{ - {NewTemplateRecord(uniqueTemplateID, 12, false), testIEs, valData{}}, + {NewTemplateRecord(uniqueTemplateID, 14, false), testIEs, valData{}}, {NewDataRecord(uniqueTemplateID, len(testIEs), 0, false), testIEs, values}, } @@ -124,9 +130,13 @@ func TestAddInfoElements(t *testing.T) { case "dataRecordsReliability": ie = NewBoolInfoElement(testIE, test.valList.dataReliable) case "flowStartSeconds": - ie = NewDateTimeSecondsInfoElement(testIE, test.valList.flowStartSecs) + ie = NewDateTimeInfoElement(testIE, test.valList.flowStartSecs) case "flowStartMilliseconds": - ie = NewDateTimeMillisecondsInfoElement(testIE, test.valList.flowStartMillisecs) + ie = NewDateTimeInfoElement(testIE, test.valList.flowStartMillisecs) + case "flowStartMicroseconds": + ie = NewDateTimeInfoElement(testIE, test.valList.flowStartMicrosecs) + case "flowStartNanoseconds": + ie = NewDateTimeInfoElement(testIE, test.valList.flowStartNanosecs) case "sourceMacAddress": ie = NewMacAddressInfoElement(testIE, test.valList.macAddr) case "sourceIPv4Address": @@ -196,8 +206,8 @@ func TestGetElementMap(t *testing.T) { macAddr net.HardwareAddr ipAddr net.IP stringVal string - flowStartSecs uint32 - flowStartMillisecs uint64 + flowStartSecs time.Time + flowStartMillisecs time.Time } valList := valData{ uint8(0x1), // ICMP proto @@ -210,8 +220,8 @@ func TestGetElementMap(t *testing.T) { macAddress, // mac address net.ParseIP("1.2.3.4"), // IP Address "My Interface in IPFIX lib", // String - uint32(time.Now().Unix()), // dateTimeSeconds - uint64(time.Now().Unix()), // dateTimeMilliseconds + time.Now(), // dateTimeSeconds + time.Now(), // dateTimeMilliseconds } record := NewDataRecord(uniqueTemplateID, len(ieList), 0, false) @@ -233,9 +243,9 @@ func TestGetElementMap(t *testing.T) { case "dataRecordsReliability": ie = NewBoolInfoElement(testIE, valList.dataReliable) case "flowStartSeconds": - ie = NewDateTimeSecondsInfoElement(testIE, valList.flowStartSecs) + ie = NewDateTimeInfoElement(testIE, valList.flowStartSecs) case "flowStartMilliseconds": - ie = NewDateTimeMillisecondsInfoElement(testIE, valList.flowStartMillisecs) + ie = NewDateTimeInfoElement(testIE, valList.flowStartMillisecs) case "sourceMacAddress": ie = NewMacAddressInfoElement(testIE, valList.macAddr) case "sourceIPv4Address": diff --git a/pkg/exporter/process.go b/pkg/exporter/process.go index d2658097..47eaad1e 100644 --- a/pkg/exporter/process.go +++ b/pkg/exporter/process.go @@ -341,12 +341,8 @@ func (ep *ExportingProcess) createAndSendJSONMsg(set entities.Set) (int, error) elements[element.GetName()] = element.GetFloat64Value() case entities.Boolean: elements[element.GetName()] = element.GetBooleanValue() - case entities.DateTimeSeconds: - elements[element.GetName()] = element.GetUnsigned32Value() - case entities.DateTimeMilliseconds: - elements[element.GetName()] = element.GetUnsigned64Value() - case entities.DateTimeMicroseconds, entities.DateTimeNanoseconds: - return bytesSent, fmt.Errorf("API does not support micro and nano seconds types yet") + case entities.DateTimeSeconds, entities.DateTimeMilliseconds, entities.DateTimeMicroseconds, entities.DateTimeNanoseconds: + elements[element.GetName()] = element.GetDateTimeValue() case entities.MacAddress: elements[element.GetName()] = element.GetMacAddressValue() case entities.Ipv4Address, entities.Ipv6Address: diff --git a/pkg/intermediate/aggregate_test.go b/pkg/intermediate/aggregate_test.go index f73d4b36..925a1dd5 100644 --- a/pkg/intermediate/aggregate_test.go +++ b/pkg/intermediate/aggregate_test.go @@ -122,7 +122,7 @@ func createMsgwithTemplateSet(isIPv6 bool) *entities.Message { ie2 = entities.NewIPAddressInfoElement(entities.NewInfoElement("destinationIPv6Address", 12, 19, 0, 16), nil) ie8 = entities.NewIPAddressInfoElement(entities.NewInfoElement("destinationClusterIPv6", 106, 19, registry.AntreaEnterpriseID, 16), nil) } - ie10 := entities.NewDateTimeSecondsInfoElement(entities.NewInfoElement("flowEndSeconds", 151, 14, 0, 4), 0) + ie10 := entities.NewDateTimeInfoElement(entities.NewInfoElement("flowEndSeconds", 151, 14, 0, 4), time.Time{}) ie11 := entities.NewUnsigned8InfoElement(entities.NewInfoElement("flowType", 137, 1, registry.AntreaEnterpriseID, 1), 0) ie12 := entities.NewUnsigned8InfoElement(entities.NewInfoElement("ingressNetworkPolicyRuleAction", 139, 1, registry.AntreaEnterpriseID, 1), 0) ie13 := entities.NewUnsigned8InfoElement(entities.NewInfoElement("egressNetworkPolicyRuleAction", 140, 1, registry.AntreaEnterpriseID, 1), 0) @@ -180,11 +180,11 @@ func createDataMsgForSrc(t *testing.T, isIPv6 bool, isIntraNode bool, isUpdatedR tmpTCPState, _ := registry.GetInfoElement("tcpState", registry.AntreaEnterpriseID) if !isUpdatedRecord { - ie10 = entities.NewDateTimeSecondsInfoElement(tmpFlowEndSecs, uint32(1)) + ie10 = entities.NewDateTimeInfoElement(tmpFlowEndSecs, time.Unix(1, 0)) ie12 = entities.NewUnsigned8InfoElement(tmpFlowEndReason, registry.ActiveTimeoutReason) ie13 = entities.NewStringInfoElement(tmpTCPState, "ESTABLISHED") } else { - ie10 = entities.NewDateTimeSecondsInfoElement(tmpFlowEndSecs, uint32(10)) + ie10 = entities.NewDateTimeInfoElement(tmpFlowEndSecs, time.Unix(10, 0)) ie12 = entities.NewUnsigned8InfoElement(tmpFlowEndReason, registry.EndOfFlowReason) ie13 = entities.NewStringInfoElement(tmpTCPState, "TIME_WAIT") } @@ -206,7 +206,7 @@ func createDataMsgForSrc(t *testing.T, isIPv6 bool, isIntraNode bool, isUpdatedR } else { ie15 = entities.NewUnsigned8InfoElement(entities.NewInfoElement("egressNetworkPolicyRuleAction", 140, 1, registry.AntreaEnterpriseID, 1), registry.NetworkPolicyRuleActionNoAction) } - ie17 := entities.NewDateTimeSecondsInfoElement(tmpFlowStartSecs, uint32(0)) + ie17 := entities.NewDateTimeInfoElement(tmpFlowStartSecs, time.Time{}) elements = append(elements, ie1, ie2, ie3, ie4, ie5, ie6, ie7, ie8, ie9, ie10, ie11, ie12, ie13, ie14, ie15, ie16, ie17) // Add all elements in statsElements. @@ -266,7 +266,7 @@ func createDataMsgForDst(t *testing.T, isIPv6 bool, isIntraNode bool, isUpdatedR set.PrepareSet(entities.Data, testTemplateID) elements := make([]entities.InfoElementWithValue, 0) var srcAddr, dstAddr, svcAddr []byte - var flowStartTime, flowEndTime uint32 + var flowStartTime, flowEndTime time.Time var flowEndReason, ingressNetworkPolicyRuleAction, antreaFlowType uint8 var srcPod, dstPod, tcpState string var svcPort uint16 @@ -317,20 +317,20 @@ func createDataMsgForDst(t *testing.T, isIPv6 bool, isIntraNode bool, isUpdatedR ie2 = entities.NewIPAddressInfoElement(entities.NewInfoElement("destinationIPv6Address", 12, 19, 0, 16), dstAddr) ie8 = entities.NewIPAddressInfoElement(entities.NewInfoElement("destinationClusterIPv6", 106, 19, registry.AntreaEnterpriseID, 16), svcAddr) } - flowStartTime = uint32(0) + flowStartTime = time.Unix(0, 0) if !isUpdatedRecord { - flowEndTime = uint32(1) + flowEndTime = time.Unix(1, 0) flowEndReason = registry.ActiveTimeoutReason tcpState = "ESTABLISHED" } else { - flowEndTime = uint32(10) + flowEndTime = time.Unix(10, 0) flowEndReason = registry.EndOfFlowReason tcpState = "TIME_WAIT" } tmpElement, _ := registry.GetInfoElement("flowStartSeconds", registry.IANAEnterpriseID) - ie17 := entities.NewDateTimeSecondsInfoElement(tmpElement, flowStartTime) + ie17 := entities.NewDateTimeInfoElement(tmpElement, flowStartTime) tmpElement, _ = registry.GetInfoElement("flowEndSeconds", registry.IANAEnterpriseID) - ie10 := entities.NewDateTimeSecondsInfoElement(tmpElement, flowEndTime) + ie10 := entities.NewDateTimeInfoElement(tmpElement, flowEndTime) if !isIntraNode { antreaFlowType = registry.FlowTypeInterNode } else { diff --git a/pkg/test/util.go b/pkg/test/util.go index 052677e1..abea4633 100644 --- a/pkg/test/util.go +++ b/pkg/test/util.go @@ -16,6 +16,7 @@ package test import ( "net" + "time" "github.com/vmware/go-ipfix/pkg/entities" "github.com/vmware/go-ipfix/pkg/registry" @@ -67,8 +68,8 @@ type testRecord struct { srcPort uint16 dstPort uint16 proto uint8 - flowStart uint32 - flowEnd uint32 + flowStart time.Time + flowEnd time.Time pktCount uint64 pktDelta uint64 srcPod string @@ -101,9 +102,9 @@ func getTestRecord(isSrcNode, isIPv6 bool) testRecord { record.srcIP = net.ParseIP("2001:0:3238:DFE1:63::FEFB") record.dstIP = net.ParseIP("2001:0:3238:DFE1:63::FEFC") } - record.flowStart = uint32(1257893000) + record.flowStart = time.Unix(1257893000, 0) if !isSrcNode { - record.flowEnd = uint32(1257896000) + record.flowEnd = time.Unix(1257896000, 0) record.pktCount = uint64(1000) record.pktDelta = uint64(500) record.bytCount = uint64(1000000) @@ -119,7 +120,7 @@ func getTestRecord(isSrcNode, isIPv6 bool) testRecord { record.dstClusterIP = net.ParseIP("::") } } else { - record.flowEnd = uint32(1257894000) + record.flowEnd = time.Unix(1257894000, 0) record.pktCount = uint64(800) record.pktDelta = uint64(500) record.bytCount = uint64(800000) @@ -214,9 +215,9 @@ func getDataRecordElements(isSrcNode, isIPv6 bool) []entities.InfoElementWithVal case "octetTotalCount": ie = entities.NewUnsigned64InfoElement(element, testRec.bytCount) case "flowStartSeconds": - ie = entities.NewDateTimeSecondsInfoElement(element, testRec.flowStart) + ie = entities.NewDateTimeInfoElement(element, testRec.flowStart) case "flowEndSeconds": - ie = entities.NewDateTimeSecondsInfoElement(element, testRec.flowEnd) + ie = entities.NewDateTimeInfoElement(element, testRec.flowEnd) case "flowEndReason": ie = entities.NewUnsigned8InfoElement(element, testRec.flowEndReason) }