Fix #I4KI81 reason: modify kata-containers version and update it to 1.11.1 Signed-off-by: holyfei <yangfeiyu20092010@163.com>
404 lines
11 KiB
Diff
404 lines
11 KiB
Diff
From a260bbe394f91fa05b163315390ed133de5c5494 Mon Sep 17 00:00:00 2001
|
|
From: holyfei <yangfeiyu20092010@163.com>
|
|
Date: Wed, 19 Aug 2020 17:43:24 +0800
|
|
Subject: [PATCH] clock: synchronizes clock info to agent
|
|
|
|
reason: virtual machine's clock may be incorrect, proxy synchronizes
|
|
clock info to help virtual machine adjust clock time
|
|
|
|
Signed-off-by: yangfeiyu <yangfeiyu2@huawei.com>
|
|
---
|
|
proxy.go | 7 ++
|
|
proxy_test.go | 29 +++++
|
|
sync_clock_client.go | 107 +++++++++++++++++
|
|
sync_clock_client_test.go | 132 +++++++++++++++++++++
|
|
.../kata-containers/agent/pkg/clock/clock_util.go | 44 +++++++
|
|
5 files changed, 319 insertions(+)
|
|
create mode 100644 sync_clock_client.go
|
|
create mode 100644 sync_clock_client_test.go
|
|
create mode 100644 vendor/github.com/kata-containers/agent/pkg/clock/clock_util.go
|
|
|
|
diff --git a/proxy.go b/proxy.go
|
|
index ab062a5..9dfcb3c 100644
|
|
--- a/proxy.go
|
|
+++ b/proxy.go
|
|
@@ -105,6 +105,13 @@ func serve(servConn io.ReadWriteCloser, proto, addr string, results chan error)
|
|
// Start the heartbeat in a separate go routine
|
|
go heartBeat(session)
|
|
|
|
+ // start the sync clock in a separate go routine
|
|
+ syncClockStream, err := session.Open()
|
|
+ if err != nil {
|
|
+ return nil, nil, err
|
|
+ }
|
|
+ go SyncClock(syncClockStream)
|
|
+
|
|
// serving connection
|
|
l, err := net.Listen(proto, addr)
|
|
if err != nil {
|
|
diff --git a/proxy_test.go b/proxy_test.go
|
|
index 923b138..94fa523 100644
|
|
--- a/proxy_test.go
|
|
+++ b/proxy_test.go
|
|
@@ -10,6 +10,7 @@ package main
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
+ "encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
@@ -23,6 +24,7 @@ import (
|
|
"testing"
|
|
|
|
"github.com/hashicorp/yamux"
|
|
+ "github.com/kata-containers/agent/pkg/clock"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
@@ -121,6 +123,13 @@ func server(listener net.Listener, closeCh chan bool) error {
|
|
session.Close()
|
|
}()
|
|
|
|
+ // accept the sync clock stream first
|
|
+ if syncClockStream, err := session.Accept(); err != nil {
|
|
+ return err
|
|
+ } else {
|
|
+ go serverSyncClock(syncClockStream)
|
|
+ }
|
|
+
|
|
for {
|
|
stream, err := session.Accept()
|
|
if err != nil {
|
|
@@ -133,6 +142,26 @@ func server(listener net.Listener, closeCh chan bool) error {
|
|
}
|
|
}
|
|
|
|
+func serverSyncClock(stream net.Conn) {
|
|
+ for {
|
|
+ buf, byteNum, err := readConnData(stream)
|
|
+ if err != nil {
|
|
+ continue
|
|
+ }
|
|
+ var clockInfo clock.TimeValue
|
|
+ if err := json.Unmarshal(buf[:byteNum], &clockInfo); err != nil {
|
|
+ continue
|
|
+ }
|
|
+ nowTime := clock.GetCurrentTimeNs()
|
|
+ clockInfo.ClientArriveTime = nowTime
|
|
+ clockInfo.ServerSendTime = nowTime
|
|
+ b, _ := json.Marshal(clockInfo)
|
|
+ if err := clock.WriteConnData(stream, b); err != nil {
|
|
+ continue
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
func TestUnixAddrParsing(T *testing.T) {
|
|
buf := "unix://foo/bar"
|
|
addr, err := unixAddr(buf)
|
|
diff --git a/sync_clock_client.go b/sync_clock_client.go
|
|
new file mode 100644
|
|
index 0000000..9bf3e91
|
|
--- /dev/null
|
|
+++ b/sync_clock_client.go
|
|
@@ -0,0 +1,107 @@
|
|
+// Copyright (c) Huawei Technologies Co., Ltd. 2018. All rights reserved.
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+// Description: sync clock client related function
|
|
+// Author: xueshaojia x00464843
|
|
+// Create: 2018-11-10
|
|
+
|
|
+package main
|
|
+
|
|
+import (
|
|
+ "encoding/json"
|
|
+ "fmt"
|
|
+ "net"
|
|
+ "time"
|
|
+
|
|
+ "github.com/kata-containers/agent/pkg/clock"
|
|
+)
|
|
+
|
|
+const (
|
|
+ allowTimeDiff = 10 * 1000 * 1000 // allow 10ms's difference
|
|
+ syncClockInterval = 60 * time.Second // sync clock with agent every 60 seconds
|
|
+ rpcTimeout = 10 * time.Second // timeout for proxy's reading data
|
|
+)
|
|
+
|
|
+// readConnData reads data from stream
|
|
+func readConnData(stream net.Conn) (buf []byte, byteNum int, err error) {
|
|
+ // set read deadline to avoid case as following:
|
|
+ // proxy and agent are both reading and then syncClock will never work
|
|
+ stream.SetReadDeadline(time.Now().Add(rpcTimeout))
|
|
+ buf = make([]byte, clock.MaxSyncClockByteNum)
|
|
+ byteNum, err = stream.Read(buf)
|
|
+ return buf, byteNum, err
|
|
+}
|
|
+
|
|
+// getGuestClock syncs guest clock info
|
|
+// sends ClientSendTime
|
|
+// waits for ClientArriveTime and ServerSendTime
|
|
+func getGuestClock(stream net.Conn, clockInfo *clock.TimeValue) error {
|
|
+ clockInfo.Delta = 0
|
|
+ b, err := json.Marshal(clockInfo)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ if err = clock.WriteConnData(stream, b); err != nil {
|
|
+ return err
|
|
+ }
|
|
+
|
|
+ buf, byteNum, err := readConnData(stream)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+
|
|
+ if err = json.Unmarshal(buf[:byteNum], clockInfo); err != nil {
|
|
+ return fmt.Errorf("sync clock, parse guest clocktime error:%v", err)
|
|
+ }
|
|
+ return nil
|
|
+}
|
|
+
|
|
+// adjustGuestClock tells server to ajust local clock with Delta
|
|
+func adjustGuestClock(stream net.Conn, clockInfo *clock.TimeValue) error {
|
|
+ b, err := json.Marshal(clockInfo)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ logger().Debugf("sync clock, send:%s", string(b))
|
|
+ return clock.WriteConnData(stream, b)
|
|
+}
|
|
+
|
|
+// syncClock performs all the steps
|
|
+// 1 get client send time[host]
|
|
+// 2 request for client arrive time and server send time[guest os]
|
|
+// 3 get server arrive time[host]
|
|
+// 4 calculate clock diff
|
|
+// 5 request to adjust guest clock
|
|
+func syncClock(stream net.Conn) error {
|
|
+ var clockInfo clock.TimeValue
|
|
+ if clockInfo.ClientSendTime = clock.GetCurrentTimeNs(); clockInfo.ClientSendTime <= 0 {
|
|
+ return fmt.Errorf("sync clock, get client sendtime error")
|
|
+ }
|
|
+ err := getGuestClock(stream, &clockInfo)
|
|
+ if err != nil {
|
|
+ return fmt.Errorf("sync clock, get guest clocktime error:%v", err)
|
|
+ }
|
|
+ if clockInfo.ServerArriveTime = clock.GetCurrentTimeNs(); clockInfo.ServerArriveTime <= 0 {
|
|
+ return fmt.Errorf("sync clock, get client recvtime error")
|
|
+ }
|
|
+ if clockInfo.ClientSendTime <= 0 || clockInfo.ClientArriveTime <= 0 || clockInfo.ServerSendTime <= 0 {
|
|
+ return fmt.Errorf("sync clock, some fields of NTP message error, raw message:%v", clockInfo)
|
|
+ }
|
|
+
|
|
+ delta := ((clockInfo.ClientSendTime - clockInfo.ClientArriveTime) + (clockInfo.ServerArriveTime - clockInfo.ServerSendTime)) / 2
|
|
+ if delta < -allowTimeDiff || delta > allowTimeDiff {
|
|
+ clockInfo.Delta = delta
|
|
+ if err := adjustGuestClock(stream, &clockInfo); err != nil {
|
|
+ return fmt.Errorf("sync clock, failed to adjust guest clock : %v", err)
|
|
+ }
|
|
+ }
|
|
+ return nil
|
|
+}
|
|
+
|
|
+func SyncClock(stream net.Conn) {
|
|
+ for {
|
|
+ if err := syncClock(stream); err != nil {
|
|
+ logger().WithError(err).Error("sync clock failed")
|
|
+ }
|
|
+ time.Sleep(syncClockInterval)
|
|
+ }
|
|
+}
|
|
diff --git a/sync_clock_client_test.go b/sync_clock_client_test.go
|
|
new file mode 100644
|
|
index 0000000..b0b1c85
|
|
--- /dev/null
|
|
+++ b/sync_clock_client_test.go
|
|
@@ -0,0 +1,132 @@
|
|
+// Copyright (c) Huawei Technologies Co., Ltd. 2018. All rights reserved.
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+// Description: sync clock client related test
|
|
+// Author: xueshaojia x00464843
|
|
+// Create: 2018-11-10
|
|
+
|
|
+package main
|
|
+
|
|
+import (
|
|
+ "encoding/json"
|
|
+ "fmt"
|
|
+ "math/rand"
|
|
+ "net"
|
|
+ "os"
|
|
+ "testing"
|
|
+
|
|
+ "github.com/hashicorp/yamux"
|
|
+ "github.com/kata-containers/agent/pkg/clock"
|
|
+)
|
|
+
|
|
+func TestReadWriteData(t *testing.T) {
|
|
+ var clockInfo clock.TimeValue
|
|
+ clockInfo.ClientSendTime = clock.GetCurrentTimeNs()
|
|
+ b, err := json.Marshal(clockInfo)
|
|
+ if err != nil {
|
|
+ t.Fatalf("Marshal clock info fail, err:%v", err)
|
|
+ }
|
|
+
|
|
+ err = clock.WriteConnData(clientStream, b)
|
|
+ fmt.Printf("client send: %s\n", string(b))
|
|
+ if err != nil {
|
|
+ t.Fatalf("send clock info fail, err:%v", err)
|
|
+ }
|
|
+ _, _, err = readConnData(clientStream)
|
|
+ if err != nil {
|
|
+ t.Fatalf("recv clock info fail, err:%v", err)
|
|
+ }
|
|
+}
|
|
+
|
|
+func SetUpServer(sock string, readyChan chan int) error {
|
|
+ var err error
|
|
+ listener, err = net.Listen("unix", sock)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ readyChan <- 1
|
|
+ conn, err := listener.Accept()
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ session, err := yamux.Server(conn, nil)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ serverSession = session
|
|
+ stream, err := session.Accept()
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ for {
|
|
+ var clockInfo clock.TimeValue
|
|
+ var byteNum int
|
|
+ var err error
|
|
+ buf := make([]byte, 400)
|
|
+ if byteNum, err = stream.Read(buf); err != nil {
|
|
+ break
|
|
+ }
|
|
+
|
|
+ if err = json.Unmarshal(buf[:byteNum], &clockInfo); err != nil {
|
|
+ break
|
|
+ }
|
|
+ if clockInfo.Delta == 0 {
|
|
+ nowTime := clock.GetCurrentTimeNs()
|
|
+ clockInfo.ClientArriveTime = nowTime
|
|
+ clockInfo.ClientArriveTime = nowTime
|
|
+ b, _ := json.Marshal(&clockInfo)
|
|
+ stream.Write(b)
|
|
+ }
|
|
+ }
|
|
+ return nil
|
|
+}
|
|
+
|
|
+func SetUpClient(sock string) error {
|
|
+ conn, err := net.Dial("unix", sock)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+ session, err := yamux.Client(conn, nil)
|
|
+ if err != nil {
|
|
+ conn.Close()
|
|
+ return err
|
|
+ }
|
|
+ clientSession = session
|
|
+ stream, err := session.Open()
|
|
+ if err != nil {
|
|
+ clientSession.Close()
|
|
+ return err
|
|
+ }
|
|
+ clientStream = stream
|
|
+ return nil
|
|
+}
|
|
+
|
|
+func TearDown() {
|
|
+ listener.Close()
|
|
+ serverSession.Close()
|
|
+ clientSession.Close()
|
|
+}
|
|
+
|
|
+func GenSocket() string {
|
|
+ randSeed := clock.GetCurrentTimeNs()
|
|
+ rand.Seed(randSeed)
|
|
+ return fmt.Sprintf("/tmp/%d.sock", rand.Uint32())
|
|
+}
|
|
+
|
|
+var listener net.Listener
|
|
+var clientStream net.Conn
|
|
+var serverSession *yamux.Session
|
|
+var clientSession *yamux.Session
|
|
+
|
|
+func TestMain(m *testing.M) {
|
|
+ waitConn := make(chan int)
|
|
+ testSock := GenSocket()
|
|
+ go SetUpServer(testSock, waitConn)
|
|
+ <-waitConn
|
|
+ if err := SetUpClient(testSock); err != nil {
|
|
+ listener.Close()
|
|
+ serverSession.Close()
|
|
+ os.Exit(1)
|
|
+ }
|
|
+ m.Run()
|
|
+ TearDown()
|
|
+}
|
|
diff --git a/vendor/github.com/kata-containers/agent/pkg/clock/clock_util.go b/vendor/github.com/kata-containers/agent/pkg/clock/clock_util.go
|
|
new file mode 100644
|
|
index 0000000..03244fd
|
|
--- /dev/null
|
|
+++ b/vendor/github.com/kata-containers/agent/pkg/clock/clock_util.go
|
|
@@ -0,0 +1,44 @@
|
|
+// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+// Description: common functions
|
|
+// Author: jiangpeifei
|
|
+// Create: 2019-05-28
|
|
+
|
|
+package clock
|
|
+
|
|
+import (
|
|
+ "net"
|
|
+ "syscall"
|
|
+)
|
|
+
|
|
+type TimeValue struct {
|
|
+ ClientSendTime int64 `json:"client_send_time"`
|
|
+ ClientArriveTime int64 `json:"client_arrive_time"`
|
|
+ ServerSendTime int64 `json:"server_send_time"`
|
|
+ ServerArriveTime int64 `json:"server_arrive_time"`
|
|
+ Delta int64 `json:"delta"`
|
|
+}
|
|
+
|
|
+const MaxSyncClockByteNum = 400 //sync clock byte num, max=400
|
|
+
|
|
+// getCurrentTimeNs returns UTC time in Ns
|
|
+func GetCurrentTimeNs() int64 {
|
|
+ var tv syscall.Timeval
|
|
+ if err := syscall.Gettimeofday(&tv); err != nil {
|
|
+ return -1
|
|
+ }
|
|
+ return tv.Sec*1000000000 + tv.Usec*1000
|
|
+}
|
|
+
|
|
+// readConnData reads data from stream
|
|
+func ReadConnData(stream net.Conn) (buf []byte, byteNum int, err error) {
|
|
+ buf = make([]byte, MaxSyncClockByteNum)
|
|
+ byteNum, err = stream.Read(buf)
|
|
+ return buf, byteNum, err
|
|
+}
|
|
+
|
|
+// writeConnData writes data to stream
|
|
+func WriteConnData(stream net.Conn, buf []byte) error {
|
|
+ _, err := stream.Write(buf)
|
|
+ return err
|
|
+}
|
|
--
|
|
2.14.3 (Apple Git-98)
|
|
|