/
fwd_pipe.go
111 lines (95 loc) · 3.43 KB
/
fwd_pipe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package client
import (
"context"
"fmt"
"io/ioutil"
//nolint:staticcheck // SA1019 To be resolved later
//lint:ignore SA1019 This line added for support golint version of VSC
"github.com/golang/protobuf/proto"
p4_config_v1 "github.com/p4lang/p4runtime/go/p4/config/v1"
p4_v1 "github.com/p4lang/p4runtime/go/p4/v1"
)
type FwdPipeConfig struct {
P4Info *p4_config_v1.P4Info
P4DeviceConfig []byte
Cookie uint64
}
func (c *Client) SetFwdPipeFromBytes(binBytes, p4infoBytes []byte, cookie uint64) (*FwdPipeConfig, error) {
p4Info := &p4_config_v1.P4Info{}
if err := proto.UnmarshalText(string(p4infoBytes), p4Info); err != nil {
return nil, fmt.Errorf("failed to decode P4Info Protobuf message: %v", err)
}
config := &p4_v1.ForwardingPipelineConfig{
P4Info: p4Info,
P4DeviceConfig: binBytes,
Cookie: &p4_v1.ForwardingPipelineConfig_Cookie{
Cookie: cookie,
},
}
req := &p4_v1.SetForwardingPipelineConfigRequest{
DeviceId: c.deviceID,
ElectionId: &c.electionID,
Action: p4_v1.SetForwardingPipelineConfigRequest_VERIFY_AND_COMMIT,
Config: config,
}
_, err := c.SetForwardingPipelineConfig(context.Background(), req)
if err == nil {
c.p4Info = p4Info
return &FwdPipeConfig{
P4Info: p4Info,
P4DeviceConfig: binBytes,
Cookie: cookie,
}, nil
}
return nil, err
}
func (c *Client) SetFwdPipe(binPath string, p4infoPath string, cookie uint64) (*FwdPipeConfig, error) {
binBytes, err := ioutil.ReadFile(binPath)
if err != nil {
return nil, fmt.Errorf("error when reading binary device config: %v", err)
}
p4infoBytes, err := ioutil.ReadFile(p4infoPath)
if err != nil {
return nil, fmt.Errorf("error when reading P4Info text file: %v", err)
}
return c.SetFwdPipeFromBytes(binBytes, p4infoBytes, cookie)
}
type GetFwdPipeResponseType int32
const (
GetFwdPipeAll = GetFwdPipeResponseType(p4_v1.GetForwardingPipelineConfigRequest_ALL)
GetFwdPipeCookieOnly = GetFwdPipeResponseType(p4_v1.GetForwardingPipelineConfigRequest_COOKIE_ONLY)
GetFwdPipeP4InfoAndCookie = GetFwdPipeResponseType(p4_v1.GetForwardingPipelineConfigRequest_P4INFO_AND_COOKIE)
GetFwdPipeDeviceConfigAndCookie = GetFwdPipeResponseType(p4_v1.GetForwardingPipelineConfigRequest_DEVICE_CONFIG_AND_COOKIE)
)
// GetFwdPipe retrieves the current pipeline config used in the remote switch.
//
// responseType is oneof:
// GetFwdPipeAll, GetFwdPipeCookieOnly, GetFwdPipeP4InfoAndCookie, GetFwdPipeDeviceConfigAndCookie
// See https://p4.org/p4runtime/spec/v1.3.0/P4Runtime-Spec.html#sec-getforwardingpipelineconfig-rpc
func (c *Client) GetFwdPipe(responseType GetFwdPipeResponseType) (*FwdPipeConfig, error) {
req := &p4_v1.GetForwardingPipelineConfigRequest{
DeviceId: c.deviceID,
ResponseType: p4_v1.GetForwardingPipelineConfigRequest_ResponseType(responseType),
}
resp, err := c.GetForwardingPipelineConfig(context.Background(), req)
if err != nil {
return nil, fmt.Errorf("error when retrieving forwardingpipeline config: %v", err)
}
config := resp.GetConfig()
if config == nil {
// pipeline doesn't have a config yet
return nil, nil
}
var pipeConfig = &FwdPipeConfig{
P4Info: config.GetP4Info(),
P4DeviceConfig: config.GetP4DeviceConfig(),
}
if Cookie := config.GetCookie(); Cookie != nil {
pipeConfig.Cookie = Cookie.GetCookie()
}
// save P4info for later use
if pipeConfig.P4Info != nil {
c.p4Info = pipeConfig.P4Info
}
return pipeConfig, nil
}