133 lines
3.3 KiB
Go
133 lines
3.3 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package vpp
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"go.fd.io/govpp/api"
|
|
|
|
"git.ipng.ch/ipng/vpp-maglev/internal/metrics"
|
|
)
|
|
|
|
// loggedChannel wraps an api.Channel so that every VPP request/reply is
|
|
// recorded via slog at DEBUG level. All code in this package MUST send VPP
|
|
// messages through a loggedChannel (via Client.apiChannel) so we have a
|
|
// complete audit trail of what was sent to the dataplane.
|
|
type loggedChannel struct {
|
|
ch api.Channel
|
|
}
|
|
|
|
// apiChannel opens a new API channel wrapped in logging. This is the only
|
|
// approved way to talk to VPP; do not call conn.NewAPIChannel directly.
|
|
func (c *Client) apiChannel() (*loggedChannel, error) {
|
|
c.mu.Lock()
|
|
conn := c.apiConn
|
|
c.mu.Unlock()
|
|
if conn == nil {
|
|
return nil, errNotConnected
|
|
}
|
|
ch, err := conn.NewAPIChannel()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &loggedChannel{ch: ch}, nil
|
|
}
|
|
|
|
// Close closes the underlying channel.
|
|
func (lc *loggedChannel) Close() { lc.ch.Close() }
|
|
|
|
// SendRequest logs the outgoing message and returns a wrapped request context.
|
|
func (lc *loggedChannel) SendRequest(msg api.Message) *loggedRequestCtx {
|
|
name := msg.GetMessageName()
|
|
slog.Debug("vpp-api-send",
|
|
"msg", name,
|
|
"crc", msg.GetCrcString(),
|
|
"payload", fmt.Sprintf("%+v", msg),
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(name, "send", "success").Inc()
|
|
return &loggedRequestCtx{
|
|
ctx: lc.ch.SendRequest(msg),
|
|
name: name,
|
|
}
|
|
}
|
|
|
|
// SendMultiRequest logs the outgoing message and returns a wrapped multi-request context.
|
|
func (lc *loggedChannel) SendMultiRequest(msg api.Message) *loggedMultiRequestCtx {
|
|
name := msg.GetMessageName()
|
|
slog.Debug("vpp-api-send-multi",
|
|
"msg", name,
|
|
"crc", msg.GetCrcString(),
|
|
"payload", fmt.Sprintf("%+v", msg),
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(name, "send", "success").Inc()
|
|
return &loggedMultiRequestCtx{
|
|
ctx: lc.ch.SendMultiRequest(msg),
|
|
name: name,
|
|
}
|
|
}
|
|
|
|
// loggedRequestCtx wraps api.RequestCtx and logs the reply on ReceiveReply.
|
|
type loggedRequestCtx struct {
|
|
ctx api.RequestCtx
|
|
name string
|
|
}
|
|
|
|
func (r *loggedRequestCtx) ReceiveReply(msg api.Message) error {
|
|
err := r.ctx.ReceiveReply(msg)
|
|
if err != nil {
|
|
slog.Debug("vpp-api-recv",
|
|
"req", r.name,
|
|
"reply", msg.GetMessageName(),
|
|
"err", err,
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(r.name, "recv", "failure").Inc()
|
|
return err
|
|
}
|
|
slog.Debug("vpp-api-recv",
|
|
"req", r.name,
|
|
"reply", msg.GetMessageName(),
|
|
"payload", fmt.Sprintf("%+v", msg),
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(r.name, "recv", "success").Inc()
|
|
return nil
|
|
}
|
|
|
|
// loggedMultiRequestCtx wraps api.MultiRequestCtx and logs each reply.
|
|
type loggedMultiRequestCtx struct {
|
|
ctx api.MultiRequestCtx
|
|
name string
|
|
seq int
|
|
}
|
|
|
|
func (r *loggedMultiRequestCtx) ReceiveReply(msg api.Message) (bool, error) {
|
|
stop, err := r.ctx.ReceiveReply(msg)
|
|
if err != nil {
|
|
slog.Debug("vpp-api-recv-multi",
|
|
"req", r.name,
|
|
"reply", msg.GetMessageName(),
|
|
"seq", r.seq,
|
|
"err", err,
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(r.name, "recv", "failure").Inc()
|
|
return stop, err
|
|
}
|
|
if stop {
|
|
slog.Debug("vpp-api-recv-multi-done",
|
|
"req", r.name,
|
|
"count", r.seq,
|
|
)
|
|
return stop, nil
|
|
}
|
|
slog.Debug("vpp-api-recv-multi",
|
|
"req", r.name,
|
|
"reply", msg.GetMessageName(),
|
|
"seq", r.seq,
|
|
"payload", fmt.Sprintf("%+v", msg),
|
|
)
|
|
metrics.VPPAPITotal.WithLabelValues(r.name, "recv", "success").Inc()
|
|
r.seq++
|
|
return stop, nil
|
|
}
|