diff --git a/containers/container.go b/containers/container.go index 7e236f50..a8541785 100644 --- a/containers/container.go +++ b/containers/container.go @@ -737,6 +737,18 @@ func (c *Container) onL7Request(pid uint32, fd uint64, timestamp uint64, r *l7.R if timestamp != 0 && conn.Timestamp != timestamp { return nil } + if conn.dstWorkload.Namespace == "external" && (r.Protocol == l7.ProtocolHTTP || r.Protocol == l7.ProtocolHTTP2) { + if host, ok := iqfqdn[conn.DestinationKey.ActualDestination().IP()]; ok { + log.Printf("Setting external host %s", host) + conn.dstWorkload.Name = host + } else { + host, error := l7.ParseHostFromHttpRequest(string(r.Payload)) + if error == nil { + conn.dstWorkload.Name = host + } + } + } + stats := c.l7Stats.get(r.Protocol, conn.DestinationKey, r, conn.srcWorkload, conn.DestinationKey.GetDestinationWorkload(), conn.DestinationKey.GetActualDestinationWorkload()) trace := c.tracer.NewTrace(conn.DestinationKey.ActualDestinationIfKnown(), conn.srcWorkload, conn.DestinationKey.GetDestinationWorkload(), conn.DestinationKey.GetActualDestinationWorkload()) @@ -747,13 +759,12 @@ func (c *Container) onL7Request(pid uint32, fd uint64, timestamp uint64, r *l7.R method := "" uri := "" response := "" - host := "" + host := conn.dstWorkload.Name headers := http.Header{} req, err := l7.ParseHTTPRequest(r.Payload) if err != nil { log.Printf("Failed to parse payload %s, %q", err, string(r.Payload)) method, uri = l7.ParseHttp(r.Payload) - host, _ = l7.ParseHostFromHttpRequest(string(r.Payload)) } else { if req != nil && req.Body != nil { body, _ := io.ReadAll(req.Body) @@ -768,7 +779,6 @@ func (c *Container) onL7Request(pid uint32, fd uint64, timestamp uint64, r *l7.R klog.Warningf("Non-utf8 characters in uri %q", req.URL.Path) uri = string([]rune(req.URL.Path)) } - host = req.Host if req.Header != nil { headers = req.Header } diff --git a/containers/l7.go b/containers/l7.go index 3da4c98c..274bd093 100644 --- a/containers/l7.go +++ b/containers/l7.go @@ -75,14 +75,6 @@ func (s L7Stats) get(protocol l7.Protocol, key common.DestinationKey, r *l7.Requ log.Printf("Failed to parse path %s", path) } constLabels["method"] = method - if dstWorkload.Namespace == "external" { - host, err := l7.ParseHostFromHttpRequest(string(r.Payload)) - if host != "" { - constLabels["destination_workload_name"] = host - } else { - log.Printf("Failed to parse host %s , %v", string(r.Payload), err) - } - } hOpts := L7Latency[protocol] m.Latency = prometheus.NewHistogram( prometheus.HistogramOpts{Name: hOpts.Name, Help: hOpts.Help, ConstLabels: constLabels}, diff --git a/ebpftracer/tracer.go b/ebpftracer/tracer.go index 3da3678d..fd8d4da1 100644 --- a/ebpftracer/tracer.go +++ b/ebpftracer/tracer.go @@ -388,11 +388,32 @@ func runEventsReader(name string, r *perf.Reader, ch chan<- Event, typ perfMapTy v := &l7Event{} data := rec.RawSample reader := bytes.NewBuffer(data) + + // Ensure binary.Read does not fail before proceeding if err := binary.Read(reader, binary.LittleEndian, v); err != nil { klog.Warningln("failed to read msg:", err) continue } + payload := reader.Bytes() + expectedSize := int(v.PayloadSize) + int(v.ResponseSize) + + // If the actual payload is smaller than expected, we log a warning and adjust + if len(payload) < expectedSize { + klog.Warningf("Payload too small (got %d bytes, expected %d), adjusting sizes", len(payload), expectedSize) + } + + // Compute safe slicing limits + payloadEnd := min(int(v.PayloadSize), len(payload)) + responseEnd := min(payloadEnd+int(v.ResponseSize), len(payload)) + + // Always copy to prevent garbage data from reused buffers + payloadData := make([]byte, payloadEnd) + copy(payloadData, payload[:payloadEnd]) + + responseData := make([]byte, responseEnd-payloadEnd) + copy(responseData, payload[payloadEnd:responseEnd]) + req := &l7.RequestData{ Protocol: l7.Protocol(v.Protocol), Status: l7.Status(v.Status), @@ -401,23 +422,17 @@ func runEventsReader(name string, r *perf.Reader, ch chan<- Event, typ perfMapTy StatementId: v.StatementId, PayloadSize: v.PayloadSize, ResponseSize: v.ResponseSize, + Payload: payloadData, + Response: responseData, } - switch { - case v.PayloadSize == 0: - case v.PayloadSize > MaxPayloadSize && v.ResponseSize > MaxPayloadSize: - req.Payload = payload[:MaxPayloadSize] - req.Response = payload[MaxPayloadSize:] - case v.PayloadSize > MaxPayloadSize: - req.Payload = payload[:MaxPayloadSize] - req.Response = payload[MaxPayloadSize : MaxPayloadSize+v.ResponseSize] - case v.ResponseSize > MaxPayloadSize: - req.Payload = payload[:v.PayloadSize] - req.Response = payload[MaxPayloadSize:] - default: - req.Payload = payload[:v.PayloadSize] - req.Response = payload[MaxPayloadSize : MaxPayloadSize+v.ResponseSize] + + event = Event{ + Type: EventTypeL7Request, + Pid: v.Pid, + Fd: v.Fd, + Timestamp: v.ConnectionTimestamp, + L7Request: req, } - event = Event{Type: EventTypeL7Request, Pid: v.Pid, Fd: v.Fd, Timestamp: v.ConnectionTimestamp, L7Request: req} case perfMapTypeFileEvents: v := &fileEvent{} if err := binary.Read(bytes.NewBuffer(rec.RawSample), binary.LittleEndian, v); err != nil {