Skip to content

Commit a450591

Browse files
authored
Merge pull request #1279 from Kuromesi/prettyprint
pretty print bpf dump
2 parents bebaf18 + d6ca5c8 commit a450591

File tree

6 files changed

+245
-22
lines changed

6 files changed

+245
-22
lines changed

pkg/controller/workload/workload_processor.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ func (p *Processor) GetBpfCache() *bpf.Cache {
108108
return p.bpf
109109
}
110110

111+
func (p *Processor) GetHashName() *utils.HashName {
112+
return p.hashName
113+
}
114+
111115
func (p *Processor) processWorkloadResponse(rsp *service_discovery_v3.DeltaDiscoveryResponse, rbac *auth.Rbac) {
112116
var err error
113117

pkg/nets/nets.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ func ConvertPortToBigEndian(little uint32) uint32 {
5656
return uint32(big16)
5757
}
5858

59+
// ConvertPortToLittleEndian convert port to host order
60+
func ConvertPortToLittleEndian(big uint32) uint32 {
61+
tmp := make([]byte, 2)
62+
binary.LittleEndian.PutUint16(tmp, uint16(big))
63+
little16 := binary.BigEndian.Uint16(tmp)
64+
return uint32(little16)
65+
}
66+
5967
func CopyIpByteFromSlice(dst *[16]byte, src []byte) {
6068
len := len(src)
6169
if len != 4 && len != 16 {
@@ -64,6 +72,26 @@ func CopyIpByteFromSlice(dst *[16]byte, src []byte) {
6472
copy(dst[:], src)
6573
}
6674

75+
// IpString converts ip bytes to string, for IpV4, it checks
76+
// whether the last 12 bytes are all zeros.
77+
// TODO: this may conflict with IpV6 addresses with the same pattern,
78+
// we should find a better way to indicate the ipv4 address.
79+
func IpString(ip [16]byte) string {
80+
if isZeros(ip[5:]) {
81+
return net.IP(ip[:4]).String()
82+
}
83+
return net.IP(ip[:]).String()
84+
}
85+
86+
func isZeros(p []byte) bool {
87+
for i := 0; i < len(p); i++ {
88+
if p[i] != 0 {
89+
return false
90+
}
91+
}
92+
return true
93+
}
94+
6795
func checkIPVersion() (ipv4, ipv6 bool) {
6896
addrs, err := net.InterfaceAddrs()
6997
if err != nil {

pkg/nets/nets_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,39 @@ func TestCompareIpByte(t *testing.T) {
118118
})
119119
}
120120
}
121+
122+
func TestConvertPortToLittleEndian(t *testing.T) {
123+
tests := []struct {
124+
input uint32
125+
expected uint32
126+
}{
127+
{8080, 8080},
128+
{0x5678, 0x5678},
129+
}
130+
131+
for _, test := range tests {
132+
input := ConvertPortToBigEndian(test.input)
133+
actual := ConvertPortToLittleEndian(input)
134+
if actual != test.expected {
135+
t.Errorf("ConvertPortToLittleEndian(%#x) = %#x; expected %#x", test.input, actual, test.expected)
136+
}
137+
}
138+
}
139+
140+
func TestIpString(t *testing.T) {
141+
tests := []struct {
142+
ip [16]byte
143+
expected string
144+
}{
145+
{[16]byte{192, 168, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "192.168.0.1"},
146+
{[16]byte{192, 168, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, "c0a8:1::1"},
147+
{[16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "0.0.0.0"},
148+
}
149+
150+
for _, test := range tests {
151+
actual := IpString(test.ip)
152+
if actual != test.expected {
153+
t.Errorf("IpString(%v) = %v; expected %v", test.ip, actual, test.expected)
154+
}
155+
}
156+
}

pkg/status/api.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717
package status
1818

1919
import (
20+
"encoding/json"
21+
"fmt"
2022
"net"
23+
"strings"
2124

2225
"kmesh.net/kmesh/api/v2/workloadapi"
2326
"kmesh.net/kmesh/api/v2/workloadapi/security"
27+
"kmesh.net/kmesh/pkg/controller/workload/bpfcache"
28+
"kmesh.net/kmesh/pkg/nets"
29+
"kmesh.net/kmesh/pkg/utils"
2430
)
2531

2632
type Workload struct {
@@ -183,3 +189,161 @@ func ConvertAuthorizationPolicy(p *security.Authorization) *AuthorizationPolicy
183189

184190
return out
185191
}
192+
193+
type prettyArray[T any] []T
194+
195+
func (a prettyArray[T]) MarshalJSON() ([]byte, error) {
196+
prettified := make([]string, len(a))
197+
for i, elem := range a {
198+
prettified[i] = fmt.Sprintf("%v", elem)
199+
}
200+
201+
return json.Marshal(strings.Join(prettified, ", "))
202+
}
203+
204+
type BpfServiceValue struct {
205+
// EndpointCount is the number of endpoints for each priority.
206+
EndpointCount prettyArray[uint32] `json:"endpointCount"`
207+
LbPolicy string `json:"lbPolicy"`
208+
ServicePort prettyArray[uint32] `json:"servicePort,omitempty"`
209+
TargetPort prettyArray[uint32] `json:"targetPort,omitempty"`
210+
WaypointAddr string `json:"waypointAddr,omitempty"`
211+
WaypointPort uint32 `json:"waypointPort,omitempty"`
212+
}
213+
214+
type BpfBackendValue struct {
215+
Ip string `json:"ip"`
216+
ServiceCount uint32 `json:"serviceCount"`
217+
Services []string `json:"services"`
218+
WaypointAddr string `json:"waypointAddr,omitempty"`
219+
WaypointPort uint32 `json:"waypointPort,omitempty"`
220+
}
221+
222+
type BpfFrontendValue struct {
223+
UpstreamId string `json:"upstreamId,omitempty"`
224+
}
225+
226+
type BpfWorkloadPolicyValue struct {
227+
PolicyIds []string `json:"policyIds,omitempty"`
228+
}
229+
230+
type BpfEndpointValue struct {
231+
BackendUid string `json:"backendUid,omitempty"`
232+
}
233+
234+
type WorkloadBpfDump struct {
235+
hashName *utils.HashName
236+
237+
WorkloadPolicies []BpfWorkloadPolicyValue `json:"workloadPolicies"`
238+
Backends []BpfBackendValue `json:"backends"`
239+
Endpoints []BpfEndpointValue `json:"endpoints"`
240+
Frontends []BpfFrontendValue `json:"frontends"`
241+
Services []BpfServiceValue `json:"services"`
242+
}
243+
244+
func NewWorkloadBpfDump(hashName *utils.HashName) WorkloadBpfDump {
245+
return WorkloadBpfDump{hashName: hashName}
246+
}
247+
248+
func (wd WorkloadBpfDump) WithWorkloadPolicies(workloadPolicies []bpfcache.WorkloadPolicyValue) WorkloadBpfDump {
249+
converted := make([]BpfWorkloadPolicyValue, 0, len(workloadPolicies))
250+
for _, policy := range workloadPolicies {
251+
policyIds := []string{}
252+
for _, id := range policy.PolicyIds {
253+
policyIds = append(policyIds, wd.hashName.NumToStr(id))
254+
}
255+
converted = append(converted, BpfWorkloadPolicyValue{
256+
PolicyIds: policyIds,
257+
})
258+
}
259+
wd.WorkloadPolicies = converted
260+
return wd
261+
}
262+
263+
func (wd WorkloadBpfDump) WithBackends(backends []bpfcache.BackendValue) WorkloadBpfDump {
264+
converted := make([]BpfBackendValue, 0, len(backends))
265+
for _, backend := range backends {
266+
waypointAddr := ""
267+
if backend.WaypointAddr != [16]byte{} {
268+
waypointAddr = nets.IpString(backend.WaypointAddr)
269+
}
270+
bac := BpfBackendValue{
271+
Ip: nets.IpString(backend.Ip),
272+
ServiceCount: backend.ServiceCount,
273+
WaypointAddr: waypointAddr,
274+
WaypointPort: nets.ConvertPortToLittleEndian(backend.WaypointPort),
275+
}
276+
services := make([]string, 0, len(backend.Services))
277+
for _, s := range backend.Services {
278+
svc := wd.hashName.NumToStr(s)
279+
if svc == "" {
280+
continue
281+
}
282+
services = append(services, svc)
283+
}
284+
bac.Services = services
285+
converted = append(converted, bac)
286+
}
287+
wd.Backends = converted
288+
return wd
289+
}
290+
291+
func (wd WorkloadBpfDump) WithEndpoints(endpoints []bpfcache.EndpointValue) WorkloadBpfDump {
292+
converted := make([]BpfEndpointValue, 0, len(endpoints))
293+
for _, endpoint := range endpoints {
294+
converted = append(converted, BpfEndpointValue{
295+
BackendUid: wd.hashName.NumToStr(endpoint.BackendUid),
296+
})
297+
}
298+
wd.Endpoints = converted
299+
return wd
300+
}
301+
302+
func (wd WorkloadBpfDump) WithFrontends(frontends []bpfcache.FrontendValue) WorkloadBpfDump {
303+
converted := make([]BpfFrontendValue, 0, len(frontends))
304+
for _, frontend := range frontends {
305+
converted = append(converted, BpfFrontendValue{
306+
UpstreamId: wd.hashName.NumToStr(frontend.UpstreamId),
307+
})
308+
}
309+
wd.Frontends = converted
310+
return wd
311+
}
312+
313+
func (wd WorkloadBpfDump) WithServices(services []bpfcache.ServiceValue) WorkloadBpfDump {
314+
converted := make([]BpfServiceValue, 0, len(services))
315+
for _, s := range services {
316+
waypointAddr := ""
317+
if s.WaypointAddr != [16]byte{} {
318+
waypointAddr = nets.IpString(s.WaypointAddr)
319+
}
320+
svc := BpfServiceValue{
321+
EndpointCount: []uint32{},
322+
LbPolicy: workloadapi.LoadBalancing_Mode_name[int32(s.LbPolicy)],
323+
WaypointAddr: waypointAddr,
324+
WaypointPort: nets.ConvertPortToLittleEndian(s.WaypointPort),
325+
}
326+
327+
for _, c := range s.EndpointCount {
328+
svc.EndpointCount = append(svc.EndpointCount, c)
329+
}
330+
331+
for _, p := range s.ServicePort {
332+
if p == 0 {
333+
continue
334+
}
335+
svc.ServicePort = append(svc.ServicePort, nets.ConvertPortToLittleEndian(p))
336+
}
337+
338+
for _, p := range s.TargetPort {
339+
if p == 0 {
340+
continue
341+
}
342+
svc.TargetPort = append(svc.TargetPort, nets.ConvertPortToLittleEndian(p))
343+
}
344+
345+
converted = append(converted, svc)
346+
}
347+
wd.Services = converted
348+
return wd
349+
}

pkg/status/status_server.go

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import (
3838
"kmesh.net/kmesh/pkg/constants"
3939
"kmesh.net/kmesh/pkg/controller"
4040
"kmesh.net/kmesh/pkg/controller/ads"
41-
"kmesh.net/kmesh/pkg/controller/workload/bpfcache"
4241
"kmesh.net/kmesh/pkg/logger"
4342
"kmesh.net/kmesh/pkg/version"
4443
)
@@ -149,27 +148,19 @@ func (s *Server) checkAdsMode(w http.ResponseWriter) bool {
149148
return true
150149
}
151150

152-
type WorkloadBpfDump struct {
153-
WorkloadPolicies []bpfcache.WorkloadPolicyValue
154-
Backends []bpfcache.BackendValue
155-
Endpoints []bpfcache.EndpointValue
156-
Frontends []bpfcache.FrontendValue
157-
Services []bpfcache.ServiceValue
158-
}
159-
160151
func (s *Server) bpfWorkloadMaps(w http.ResponseWriter, r *http.Request) {
161152
if !s.checkWorkloadMode(w) {
162153
return
163154
}
164155
client := s.xdsClient
165156
bpfMaps := client.WorkloadController.Processor.GetBpfCache()
166-
workloadBpfDump := WorkloadBpfDump{
167-
WorkloadPolicies: bpfMaps.WorkloadPolicyLookupAll(),
168-
Backends: bpfMaps.BackendLookupAll(),
169-
Endpoints: bpfMaps.EndpointLookupAll(),
170-
Frontends: bpfMaps.FrontendLookupAll(),
171-
Services: bpfMaps.ServiceLookupAll(),
172-
}
157+
workloadBpfDump := NewWorkloadBpfDump(s.xdsClient.WorkloadController.Processor.GetHashName()).
158+
WithBackends(bpfMaps.BackendLookupAll()).
159+
WithEndpoints(bpfMaps.EndpointLookupAll()).
160+
WithFrontends(bpfMaps.FrontendLookupAll()).
161+
WithServices(bpfMaps.ServiceLookupAll()).
162+
WithWorkloadPolicies(bpfMaps.WorkloadPolicyLookupAll())
163+
173164
printWorkloadBpfDump(w, workloadBpfDump)
174165
}
175166

@@ -458,9 +449,9 @@ func (s *Server) configDumpAds(w http.ResponseWriter, r *http.Request) {
458449
}
459450

460451
type WorkloadDump struct {
461-
Workloads []*Workload
462-
Services []*Service
463-
Policies []*AuthorizationPolicy
452+
Workloads []*Workload `json:"workloads"`
453+
Services []*Service `json:"services"`
454+
Policies []*AuthorizationPolicy `json:"policies"`
464455
}
465456

466457
func (s *Server) configDumpWorkload(w http.ResponseWriter, r *http.Request) {

pkg/status/testdata/workload_configdump.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"Workloads": [
2+
"workloads": [
33
{
44
"uid": "cluster0//Pod/ns/name",
55
"addresses": [
@@ -27,7 +27,7 @@
2727
]
2828
}
2929
],
30-
"Services": [
30+
"services": [
3131
{
3232
"name": "svc",
3333
"namespace": "ns",
@@ -51,7 +51,7 @@
5151
}
5252
}
5353
],
54-
"Policies": [
54+
"policies": [
5555
{
5656
"name": "policy",
5757
"namespace": "ns",

0 commit comments

Comments
 (0)