aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2020-10-23 11:40:18 +0200
committerOndrej Fabry <ofabry@cisco.com>2020-10-30 10:00:00 +0000
commit0f46871b4cc45f2c3bd5bdb0aa0f7615795a2c6d (patch)
tree3d3de8febc3e2becfbbbd648538fc5dd1748374f
parentcb540dc166c12180adba024d5b8fd463d2582928 (diff)
Fix encoding for float64 and generate conversion for Timestamp
- fixes encoding/decoding of float64 - uses little endian (contrary to all other types) - generates helper methods for vpe_types.Timestamp type - adds usage code to simple-client and binapi-types examples Change-Id: I2e83eee0629eb67964049406c50c7ee0a692ccaf Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
-rw-r--r--binapi/vpe_types/vpe_types.ba.go28
-rw-r--r--binapigen/gen_helpers.go47
-rw-r--r--binapigen/gen_helpers_test.go27
-rw-r--r--binapigen/generate.go2
-rw-r--r--codec/codec.go4
-rw-r--r--examples/binapi-types/binapi_types.go43
-rw-r--r--examples/simple-client/simple_client.go17
7 files changed, 142 insertions, 26 deletions
diff --git a/binapi/vpe_types/vpe_types.ba.go b/binapi/vpe_types/vpe_types.ba.go
index 473880d..b4d324f 100644
--- a/binapi/vpe_types/vpe_types.ba.go
+++ b/binapi/vpe_types/vpe_types.ba.go
@@ -15,6 +15,7 @@ package vpe_types
import (
"strconv"
+ "time"
api "git.fd.io/govpp.git/api"
)
@@ -79,6 +80,33 @@ type Timedelta float64
// Timestamp defines alias 'timestamp'.
type Timestamp float64
+func NewTimestamp(t time.Time) Timestamp {
+ sec := int64(t.Unix())
+ nsec := int32(t.Nanosecond())
+ ns := float64(sec) + float64(nsec/1e9)
+ return Timestamp(ns)
+}
+func (x Timestamp) ToTime() time.Time {
+ ns := int64(x * 1e9)
+ sec := ns / 1e9
+ nsec := ns % 1e9
+ return time.Unix(sec, nsec)
+}
+func (x Timestamp) String() string {
+ return x.ToTime().String()
+}
+func (x *Timestamp) MarshalText() ([]byte, error) {
+ return []byte(x.ToTime().Format(time.RFC3339Nano)), nil
+}
+func (x *Timestamp) UnmarshalText(text []byte) error {
+ t, err := time.Parse(time.RFC3339Nano, string(text))
+ if err != nil {
+ return err
+ }
+ *x = NewTimestamp(t)
+ return nil
+}
+
// Version defines type 'version'.
type Version struct {
Major uint32 `binapi:"u32,name=major" json:"major,omitempty"`
diff --git a/binapigen/gen_helpers.go b/binapigen/gen_helpers.go
index 5eafc76..944bfe2 100644
--- a/binapigen/gen_helpers.go
+++ b/binapigen/gen_helpers.go
@@ -22,6 +22,7 @@ func init() {
const (
fmtPkg = GoImportPath("fmt")
netPkg = GoImportPath("net")
+ timePkg = GoImportPath("time")
stringsPkg = GoImportPath("strings")
)
@@ -185,13 +186,6 @@ func genIPPrefixConversion(g *GenFile, structName string, ipv int) {
g.P("func (x ", structName, ") String() string {")
g.P(" ip := x.Address.String()")
g.P(" return ip + \"/\" + ", strconvPkg.Ident("Itoa"), "(int(x.Len))")
- /*if ipv == 4 {
- g.P(" mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 32)")
- } else {
- g.P(" mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 128)")
- }
- g.P(" ipnet := &", netPkg.Ident("IPNet"), "{IP: x.Address.ToIP(), Mask: mask}")
- g.P(" return ipnet.String()")*/
g.P("}")
// MarshalText method
@@ -346,3 +340,42 @@ func genMacAddressConversion(g *GenFile, structName string) {
g.P("}")
g.P()
}
+
+func genTimestampConversion(g *GenFile, structName string) {
+ // NewTimestamp method
+ g.P("func New", structName, "(t ", timePkg.Ident("Time"), ") ", structName, " {")
+ g.P(" sec := int64(t.Unix())")
+ g.P(" nsec := int32(t.Nanosecond())")
+ g.P(" ns := float64(sec) + float64(nsec / 1e9)")
+ g.P(" return ", structName, "(ns)")
+ g.P("}")
+
+ // ToTime method
+ g.P("func (x ", structName, ") ToTime() ", timePkg.Ident("Time"), " {")
+ g.P(" ns := int64(x * 1e9)")
+ g.P(" sec := ns / 1e9")
+ g.P(" nsec := ns % 1e9")
+ g.P(" return ", timePkg.Ident("Unix"), "(sec, nsec)")
+ g.P("}")
+
+ // String method
+ g.P("func (x ", structName, ") String() string {")
+ g.P(" return x.ToTime().String()")
+ g.P("}")
+
+ // MarshalText method
+ g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
+ g.P(" return []byte(x.ToTime().Format(", timePkg.Ident("RFC3339Nano"), ")), nil")
+ g.P("}")
+
+ // UnmarshalText method
+ g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
+ g.P(" t, err := ", timePkg.Ident("Parse"), "(", timePkg.Ident("RFC3339Nano"), ", string(text))")
+ g.P(" if err != nil {")
+ g.P(" return err")
+ g.P(" }")
+ g.P(" *x = New", structName, "(t)")
+ g.P(" return nil")
+ g.P("}")
+ g.P()
+}
diff --git a/binapigen/gen_helpers_test.go b/binapigen/gen_helpers_test.go
index 371fd6c..075dd8e 100644
--- a/binapigen/gen_helpers_test.go
+++ b/binapigen/gen_helpers_test.go
@@ -17,11 +17,13 @@ package binapigen
import (
"strings"
"testing"
+ "time"
. "github.com/onsi/gomega"
"git.fd.io/govpp.git/binapi/ethernet_types"
"git.fd.io/govpp.git/binapi/ip_types"
+ "git.fd.io/govpp.git/binapi/vpe_types"
)
func TestGeneratedParseAddress(t *testing.T) {
@@ -154,3 +156,28 @@ func TestGeneratedParseMACError(t *testing.T) {
_, err := ethernet_types.ParseMacAddress("malformed_mac")
Expect(err).Should(HaveOccurred())
}
+
+func TestGeneratedParseTimestamp(t *testing.T) {
+ RegisterTestingT(t)
+
+ var data = []struct {
+ input time.Time
+ result vpe_types.Timestamp
+ }{
+ {time.Unix(0, 0), vpe_types.Timestamp(0)},
+ {time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
+ vpe_types.Timestamp(9.466848e+08)},
+ }
+
+ for _, entry := range data {
+ t.Run(entry.input.String(), func(t *testing.T) {
+ ts := vpe_types.NewTimestamp(entry.input)
+ Expect(ts).To(Equal(entry.result))
+
+ Expect(entry.input.Equal(ts.ToTime())).To(BeTrue())
+
+ originTime := ts.String()
+ Expect(originTime).To(Equal(entry.input.Local().String()))
+ })
+ }
+}
diff --git a/binapigen/generate.go b/binapigen/generate.go
index 834c989..bf6df81 100644
--- a/binapigen/generate.go
+++ b/binapigen/generate.go
@@ -246,6 +246,8 @@ func genAlias(g *GenFile, alias *Alias) {
genAddressWithPrefixConversion(g, alias.GoName)
case "mac_address":
genMacAddressConversion(g, alias.GoName)
+ case "timestamp":
+ genTimestampConversion(g, alias.GoName)
}
}
diff --git a/codec/codec.go b/codec/codec.go
index 3ae578b..21354a1 100644
--- a/codec/codec.go
+++ b/codec/codec.go
@@ -156,12 +156,12 @@ func (b *Buffer) DecodeInt64() int64 {
}
func (b *Buffer) EncodeFloat64(v float64) {
- binary.BigEndian.PutUint64(b.buf[b.pos:b.pos+8], math.Float64bits(v))
+ binary.LittleEndian.PutUint64(b.buf[b.pos:b.pos+8], math.Float64bits(v))
b.pos += 8
}
func (b *Buffer) DecodeFloat64() float64 {
- v := math.Float64frombits(binary.BigEndian.Uint64(b.buf[b.pos : b.pos+8]))
+ v := math.Float64frombits(binary.LittleEndian.Uint64(b.buf[b.pos : b.pos+8]))
b.pos += 8
return v
}
diff --git a/examples/binapi-types/binapi_types.go b/examples/binapi-types/binapi_types.go
index 849ad1b..2dbaa3e 100644
--- a/examples/binapi-types/binapi_types.go
+++ b/examples/binapi-types/binapi_types.go
@@ -18,36 +18,42 @@ package main
import (
"fmt"
"log"
+ "time"
"git.fd.io/govpp.git/binapi/ethernet_types"
"git.fd.io/govpp.git/binapi/ip"
"git.fd.io/govpp.git/binapi/ip_types"
+ "git.fd.io/govpp.git/binapi/vpe_types"
"git.fd.io/govpp.git/codec"
)
func init() {
- log.SetFlags(0)
}
func main() {
- addressUnionExample()
- ipAddressExample()
+ log.SetFlags(0)
+
+ usageUnion()
+ usageAddress()
- // convert IP from string form into Address type containing union
- convertIP("10.10.1.1")
- convertIP("ff80::1")
+ // convert IP address in string form into ip_types.Address
+ convertIPAddress("10.10.1.1")
+ convertIPAddress("ff80::1")
- // convert IP from string form into Prefix type
+ // convert IP address / CIDR in string form into ip_types.Prefix
convertIPPrefix("20.10.1.1/24")
convertIPPrefix("21.10.1.1")
convertIPPrefix("ff90::1/64")
convertIPPrefix("ff91::1")
- // convert MAC address from string into MacAddress
+ // convert MAC address in string form into ethernet_types.MacAddress
convertToMacAddress("00:10:ab:4f:00:01")
+
+ // convert time.Time into vpe_types.Timestamp
+ convertToTimestamp(time.Now())
}
-func addressUnionExample() {
+func usageUnion() {
var union ip_types.AddressUnion
// initialize union using constructors
@@ -63,21 +69,17 @@ func addressUnionExample() {
union.SetIP6(ip6)
}
-func ipAddressExample() {
+func usageAddress() {
// parse string into IP address
- addrIP4, err := ip_types.ParseAddress("192.168.1.10")
+ addr, err := ip_types.ParseAddress("192.168.1.10")
if err != nil {
panic(err)
}
- /*addrIP6, err := ip_types.ParseAddress("ff:2::2")
- if err != nil {
- panic(err)
- }*/
var msg = ip.IPPuntRedirect{
IsAdd: true,
Punt: ip.PuntRedirect{
- Nh: addrIP4,
+ Nh: addr,
},
}
@@ -103,7 +105,7 @@ func ipAddressExample() {
}
}
-func convertIP(ip string) {
+func convertIPAddress(ip string) {
addr, err := ip_types.ParseAddress(ip)
if err != nil {
log.Printf("error converting IP to Address: %v", err)
@@ -135,3 +137,10 @@ func convertToMacAddress(mac string) {
fmt.Printf("MacAddress converted back to string %#v to: %s\n", parsedMac, parsedMac)
}
+
+func convertToTimestamp(t time.Time) {
+ timestamp := vpe_types.NewTimestamp(t)
+ fmt.Printf("converted time %v to: %#v\n", t, timestamp)
+
+ fmt.Printf("Timestamp converted back to string %#v to: %s\n", timestamp, timestamp)
+}
diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go
index 0898c0a..10a0ea6 100644
--- a/examples/simple-client/simple_client.go
+++ b/examples/simple-client/simple_client.go
@@ -84,6 +84,7 @@ func main() {
// use request/reply (channel API)
getVppVersion(ch)
+ getSystemTime(ch)
idx := createLoopback(ch)
interfaceDump(ch)
addIPAddress(ch, idx)
@@ -107,6 +108,22 @@ func getVppVersion(ch api.Channel) {
fmt.Println()
}
+func getSystemTime(ch api.Channel) {
+ fmt.Println("Retrieving system time..")
+
+ req := &vpe.ShowVpeSystemTime{}
+ reply := &vpe.ShowVpeSystemTimeReply{}
+
+ if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
+ logError(err, "retrieving system time")
+ return
+ }
+
+ fmt.Printf("system time: %v\n", reply.VpeSystemTime)
+ fmt.Println("OK")
+ fmt.Println()
+}
+
func createLoopback(ch api.Channel) interface_types.InterfaceIndex {
fmt.Println("Creating loopback interface..")