Skip to content
This repository has been archived by the owner on Oct 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #41 from onmetal/feature/capture_grpc
Browse files Browse the repository at this point in the history
grpc support for offload pkt capturing
  • Loading branch information
guvenc authored Nov 10, 2023
2 parents 1434b3e + c8ea585 commit a13ba02
Show file tree
Hide file tree
Showing 5 changed files with 1,572 additions and 540 deletions.
47 changes: 47 additions & 0 deletions api/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,50 @@ func ProtoStatusToStatus(dpdkStatus *proto.Status) Status {
Message: dpdkStatus.Message,
}
}

func CaptureIfaceTypeToProtoIfaceType(interfaceType string) (proto.CaptureInterfaceType, error) {
switch interfaceType {
case "pf":
return proto.CaptureInterfaceType_SINGLE_PF, nil
case "vf":
return proto.CaptureInterfaceType_SINGLE_VF, nil
default:
return 0, fmt.Errorf("unsupported interface type")
}
}

func ProtoIfaceTypeToCaptureIfaceType(interfaceType proto.CaptureInterfaceType) (string, error) {
switch interfaceType {
case proto.CaptureInterfaceType_SINGLE_PF:
return "pf", nil
case proto.CaptureInterfaceType_SINGLE_VF:
return "vf", nil
default:
return "", fmt.Errorf("unsupported interface type")
}
}

func FillCaptureIfaceInfo(interfaceInfo string, request *proto.CapturedInterface) error {
switch request.InterfaceType {
case proto.CaptureInterfaceType_SINGLE_PF:
pf_index, err := strconv.Atoi(interfaceInfo)
if err != nil {
return fmt.Errorf("error parsing pf index: %w", err)
}
request.Spec = &proto.CapturedInterface_PfIndex{PfIndex: uint32(pf_index)}
case proto.CaptureInterfaceType_SINGLE_VF:
request.Spec = &proto.CapturedInterface_VfName{VfName: []byte(interfaceInfo)}
}
return nil
}

func ProtoIfaceInfoToCaptureIfaceInfo(request *proto.CapturedInterface) (string, error) {
switch request.InterfaceType {
case proto.CaptureInterfaceType_SINGLE_PF:
return strconv.Itoa(int(request.GetPfIndex())), nil
case proto.CaptureInterfaceType_SINGLE_VF:
return string(request.GetVfName()), nil
default:
return "", fmt.Errorf("unsupported interface type")
}
}
85 changes: 84 additions & 1 deletion api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (m *TypeMeta) GetKind() string {
}

type Status struct {
Code uint32 `json:"code"`
Code uint32 `json:"code"`
Message string `json:"message"`
}

Expand Down Expand Up @@ -562,6 +562,86 @@ func (m *Version) GetStatus() Status {
return m.Status
}

type CaptureConfig struct {
SinkNodeIP *netip.Addr `json:"sink_node_ipv6,omitempty"`
UdpSrcPort uint32 `json:"udp_src_port,omitempty"`
UdpDstPort uint32 `json:"udp_dst_port,omitempty"`
}

type CaptureStart struct {
TypeMeta `json:",inline"`
CaptureStartMeta `json:"metadata"`
Spec CaptureStartSpec `json:"spec"`
Status Status `json:"status"`
}

type CaptureStartMeta struct {
Config *CaptureConfig `json:"capture_config"`
}

type CaptureStartSpec struct {
Interfaces []CaptureInterface `json:"interfaces,omitempty"`
}

func (m *CaptureStartMeta) GetName() string {
return m.Config.SinkNodeIP.String()
}

func (m *CaptureStart) GetStatus() Status {
return m.Status
}

type CaptureInterface struct {
InterfaceType string `json:"interface_type"`
InterfaceInfo string `json:"interface_info"`
}

type CaptureStop struct {
TypeMeta `json:",inline"`
CaptureStopMeta `json:"metadata"`
Spec CaptureStopSpec `json:"spec"`
Status Status `json:"status"`
}

type CaptureStopMeta struct {
}

type CaptureStopSpec struct {
InterfaceCount uint32 `json:"iface_cnt"`
}

func (m *CaptureStopMeta) GetName() string {
return "capture stopped"
}

func (m *CaptureStop) GetStatus() Status {
return m.Status
}

type CaptureStatus struct {
TypeMeta `json:",inline"`
CaptureStatusMeta `json:"metadata"`
Spec CaptureGetStatusSpec `json:"spec"`
Status Status `json:"status"`
}

type CaptureStatusMeta struct {
}

func (m *CaptureStatusMeta) GetName() string {
return "get capture status"
}

func (m *CaptureStatus) GetStatus() Status {
return m.Status
}

type CaptureGetStatusSpec struct {
OperationStatus bool `json:"operation_status"`
Config CaptureConfig `json:"capture_config"`
Interfaces []CaptureInterface `json:"interfaces,omitempty"`
}

var (
InterfaceKind = reflect.TypeOf(Interface{}).Name()
InterfaceListKind = reflect.TypeOf(InterfaceList{}).Name()
Expand All @@ -582,4 +662,7 @@ var (
InitializedKind = reflect.TypeOf(Initialized{}).Name()
VniKind = reflect.TypeOf(Vni{}).Name()
VersionKind = reflect.TypeOf(Version{}).Name()
CaptureStartKind = reflect.TypeOf(CaptureStart{}).Name()
CaptureStopKind = reflect.TypeOf(CaptureStop{}).Name()
CaptureStatusKind = reflect.TypeOf(CaptureStatus{}).Name()
)
117 changes: 117 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ type Client interface {
GetVni(ctx context.Context, vni uint32, vniType uint8, ignoredErrors ...[]uint32) (*api.Vni, error)
ResetVni(ctx context.Context, vni uint32, vniType uint8, ignoredErrors ...[]uint32) (*api.Vni, error)
GetVersion(ctx context.Context, version *api.Version, ignoredErrors ...[]uint32) (*api.Version, error)

CaptureStart(ctx context.Context, capture *api.CaptureStart, ignoredErrors ...[]uint32) (*api.CaptureStart, error)
CaptureStop(ctx context.Context, ignoredErrors ...[]uint32) (*api.CaptureStop, error)
CaptureStatus(ctx context.Context, ignoredErrors ...[]uint32) (*api.CaptureStatus, error)
}

type client struct {
Expand Down Expand Up @@ -1042,3 +1046,116 @@ func (c *client) GetVersion(ctx context.Context, version *api.Version, ignoredEr
version.Spec.ServiceVersion = res.ServiceVersion
return version, nil
}

func (c *client) CaptureStart(ctx context.Context, capture *api.CaptureStart, ignoredErrors ...[]uint32) (*api.CaptureStart, error) {
var interfaces = make([]*dpdkproto.CapturedInterface, 0, len(capture.Spec.Interfaces))

for _, iface := range capture.Spec.Interfaces {
protoInterface := &dpdkproto.CapturedInterface{}

captureIfacetype, err := api.CaptureIfaceTypeToProtoIfaceType(iface.InterfaceType)
if err != nil {
fmt.Printf("error converting interface type for interface %s\n", iface.InterfaceInfo)
continue
}

protoInterface.InterfaceType = captureIfacetype
err = api.FillCaptureIfaceInfo(iface.InterfaceInfo, protoInterface)
if err != nil {
fmt.Printf("error filling interface info for interface %s\n", iface.InterfaceInfo)
continue
}

interfaces = append(interfaces, protoInterface)
}

res, err := c.DPDKonmetalClient.CaptureStart(ctx, &dpdkproto.CaptureStartRequest{
CaptureConfig: &dpdkproto.CaptureConfig{
SinkNodeIp: api.NetIPAddrToProtoIpAddress(*capture.CaptureStartMeta.Config.SinkNodeIP),
UdpSrcPort: capture.CaptureStartMeta.Config.UdpSrcPort,
UdpDstPort: capture.CaptureStartMeta.Config.UdpDstPort,
Interfaces: interfaces,
},
})

if err != nil {
return &api.CaptureStart{}, err
}
capture.Status = api.ProtoStatusToStatus(res.Status)
if res.GetStatus().GetCode() != 0 {
return capture, errors.GetError(res.Status, ignoredErrors)
}

return capture, nil
}

func (c *client) CaptureStop(ctx context.Context, ignoredErrors ...[]uint32) (*api.CaptureStop, error) {
res, err := c.DPDKonmetalClient.CaptureStop(ctx, &dpdkproto.CaptureStopRequest{})
if err != nil {
return &api.CaptureStop{}, err
}
if res.GetStatus().GetCode() != 0 {
return &api.CaptureStop{}, errors.GetError(res.Status, ignoredErrors)
}

capture := &api.CaptureStop{
Spec: api.CaptureStopSpec{
InterfaceCount: res.StoppedInterfaceCnt,
},
Status: api.ProtoStatusToStatus(res.Status),
}

return capture, nil
}

func (c *client) CaptureStatus(ctx context.Context, ignoredErrors ...[]uint32) (*api.CaptureStatus, error) {
res, err := c.DPDKonmetalClient.CaptureStatus(ctx, &dpdkproto.CaptureStatusRequest{})
if err != nil {
return &api.CaptureStatus{}, err
}
if res.GetStatus().GetCode() != 0 {
return &api.CaptureStatus{}, errors.GetError(res.Status, ignoredErrors)
}

if !res.IsActive {
capture := &api.CaptureStatus{
Spec: api.CaptureGetStatusSpec{
OperationStatus: false,
},
Status: api.ProtoStatusToStatus(res.Status),
}
return capture, nil
}

capture_interfaces := make([]api.CaptureInterface, len(res.CaptureConfig.Interfaces))
for i, cap_iface := range res.CaptureConfig.Interfaces {
capture_interfaces[i].InterfaceType, err = api.ProtoIfaceTypeToCaptureIfaceType(cap_iface.InterfaceType)
if err != nil {
return &api.CaptureStatus{}, err
}
capture_interfaces[i].InterfaceInfo, err = api.ProtoIfaceInfoToCaptureIfaceInfo(cap_iface)
if err != nil {
return &api.CaptureStatus{}, err
}
}

sink_ip, err := api.ProtoIpAddressToNetIPAddr(res.CaptureConfig.SinkNodeIp)
if err != nil {
return &api.CaptureStatus{}, err
}

capture := &api.CaptureStatus{
Spec: api.CaptureGetStatusSpec{
OperationStatus: true,
Config: api.CaptureConfig{
SinkNodeIP: sink_ip,
UdpSrcPort: res.CaptureConfig.UdpSrcPort,
UdpDstPort: res.CaptureConfig.UdpDstPort,
},
Interfaces: capture_interfaces,
},
Status: api.ProtoStatusToStatus(res.Status),
}

return capture, nil
}
Loading

0 comments on commit a13ba02

Please sign in to comment.