7 "git.fd.io/govpp.git/adapter"
8 "git.fd.io/govpp.git/adapter/vppapiclient"
9 "git.fd.io/govpp.git/api"
10 "git.fd.io/govpp.git/core"
11 "git.fd.io/govpp.git/examples/bin_api/interfaces"
12 "git.fd.io/govpp.git/examples/bin_api/vpe"
16 //////////////////////////////////////
17 ///////// Data structs ///////////
18 //////////////////////////////////////
20 const defaultStatsSocketPath = "/run/vpp/stats.sock"
21 const defaultShmPrefix = ""
23 func parseMacAddress(l2Address []byte, l2AddressLength uint32) string {
25 for i := uint32(0); i < l2AddressLength; i++ {
26 mac += fmt.Sprintf("%02x", l2Address[i])
27 if i < l2AddressLength-1 {
34 type interfaceStats struct {
45 type vppInterface struct {
46 interfaces.SwInterfaceDetails
50 type vppConnector struct {
51 statsSocketPath string
56 stats adapter.StatsAPI
58 VppDetails vpe.ShowVersionReply
59 Interfaces []*vppInterface
62 //////////////////////////////////////
63 ///////// VPP workflow ///////////
64 //////////////////////////////////////
66 func (v *vppConnector) getVppVersion() error {
67 if err := v.api.SendRequest(&vpe.ShowVersion{}).ReceiveReply(&v.VppDetails); err != nil {
68 return fmt.Errorf("failed to fetch vpp version: %v", err)
73 func (v *vppConnector) getInterfaces() error {
74 ifCtx := v.api.SendMultiRequest(&interfaces.SwInterfaceDump{})
76 ifDetails := interfaces.SwInterfaceDetails{}
77 stop, err := ifCtx.ReceiveReply(&ifDetails)
79 return fmt.Errorf("failed to fetch vpp interface: %v", err)
85 v.Interfaces = append(v.Interfaces, &vppInterface{SwInterfaceDetails: ifDetails})
90 func (v *vppConnector) connect() (err error) {
91 if v.conn, err = govpp.Connect(v.shmPrefix); err != nil {
92 return fmt.Errorf("failed to connect to vpp: %v", err)
95 if v.api, err = v.conn.NewAPIChannel(); err != nil {
96 return fmt.Errorf("failed to create api channel: %v", err)
99 v.stats = vppapiclient.NewStatClient(v.statsSocketPath)
100 if err = v.stats.Connect(); err != nil {
101 return fmt.Errorf("failed to connect to Stats adapter: %v", err)
107 func (v *vppConnector) disconnect() {
116 func (v *vppConnector) reduceCombinedCounters(stat *adapter.StatEntry) *[]adapter.CombinedCounter {
117 counters := stat.Data.(adapter.CombinedCounterStat)
118 stats := make([]adapter.CombinedCounter, len(v.Interfaces))
119 for _, workerStats := range counters {
120 for i, interfaceStats := range workerStats {
121 stats[i].Bytes += interfaceStats.Bytes
122 stats[i].Packets += interfaceStats.Packets
128 func (v *vppConnector) reduceSimpleCounters(stat *adapter.StatEntry) *[]adapter.Counter {
129 counters := stat.Data.(adapter.SimpleCounterStat)
130 stats := make([]adapter.Counter, len(v.Interfaces))
131 for _, workerStats := range counters {
132 for i, interfaceStats := range workerStats {
133 stats[i] += interfaceStats
139 func (v *vppConnector) getStatsForAllInterfaces() error {
140 statsDump, err := v.stats.DumpStats("/if")
142 return fmt.Errorf("failed to dump vpp Stats: %v", err)
145 stats := func(i int) *interfaceStats { return &v.Interfaces[uint32(i)].Stats }
147 for _, stat := range statsDump {
151 for i, counter := range *v.reduceCombinedCounters(stat) {
152 stats(i).TxBytes = uint64(counter.Bytes)
153 stats(i).TxPackets = uint64(counter.Packets)
158 for i, counter := range *v.reduceCombinedCounters(stat) {
159 stats(i).RxBytes = uint64(counter.Bytes)
160 stats(i).RxPackets = uint64(counter.Packets)
165 for i, counter := range *v.reduceSimpleCounters(stat) {
166 stats(i).TxErrors = uint64(counter)
171 for i, counter := range *v.reduceSimpleCounters(stat) {
172 stats(i).RxErrors = uint64(counter)
177 for i, counter := range *v.reduceSimpleCounters(stat) {
178 stats(i).Drops = uint64(counter)
183 for i, counter := range *v.reduceSimpleCounters(stat) {
184 stats(i).Punts = uint64(counter)
192 //////////////////////////////////////
195 statsSocketPathPtr := flag.String("stats_socket_path", defaultStatsSocketPath, "Path to vpp stats socket")
196 shmPrefixPtr := flag.String("shm_prefix", defaultShmPrefix, "Shared memory prefix (advanced)")
199 vppConn := &vppConnector{statsSocketPath: *statsSocketPathPtr, shmPrefix: *shmPrefixPtr}
200 defer vppConn.disconnect()
202 if err := vppConn.connect(); err != nil {
206 if err := vppConn.getVppVersion(); err != nil {
210 if err := vppConn.getInterfaces(); err != nil {
214 if err := vppConn.getStatsForAllInterfaces(); err != nil {
218 jsonString, err := dumpToJSONString(vppConn)
222 fmt.Println(jsonString)