|  | 
|  | 1 | +//go:build linux && (amd64 || arm64) && !aix && !ppc64 | 
|  | 2 | + | 
|  | 3 | +/* | 
|  | 4 | + * Copyright The Kmesh Authors. | 
|  | 5 | + * | 
|  | 6 | + * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 7 | + * you may not use this file except in compliance with the License. | 
|  | 8 | + * You may obtain a copy of the License at: | 
|  | 9 | + * | 
|  | 10 | + *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 11 | + * | 
|  | 12 | + * Unless required by applicable law or agreed to in writing, software | 
|  | 13 | + * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 15 | + * See the License for the specific language governing permissions and | 
|  | 16 | + * limitations under the License. | 
|  | 17 | + */ | 
|  | 18 | + | 
|  | 19 | +package bpftests | 
|  | 20 | + | 
|  | 21 | +import ( | 
|  | 22 | +	"encoding/binary" | 
|  | 23 | +	"fmt" | 
|  | 24 | +	"net" | 
|  | 25 | +	"testing" | 
|  | 26 | +) | 
|  | 27 | + | 
|  | 28 | +// TLV protocol constants and structs | 
|  | 29 | +const ( | 
|  | 30 | +	TLV_ORG_DST_ADDR_TYPE = 0x01 | 
|  | 31 | +	TLV_PAYLOAD_TYPE      = 0xFE | 
|  | 32 | +	TLV_END_LENGTH        = 0x00000000 | 
|  | 33 | +) | 
|  | 34 | + | 
|  | 35 | +// TLV header structure | 
|  | 36 | +type TLVHeader struct { | 
|  | 37 | +	Type   uint8 | 
|  | 38 | +	Length uint32 | 
|  | 39 | +} | 
|  | 40 | + | 
|  | 41 | +// TLV data content | 
|  | 42 | +type TLVData struct { | 
|  | 43 | +	IP   net.IP | 
|  | 44 | +	Port uint16 | 
|  | 45 | +} | 
|  | 46 | + | 
|  | 47 | +// ParseTLVMessage: parse TLV message | 
|  | 48 | +func ParseTLVMessage(data []byte) (*TLVData, error) { | 
|  | 49 | +	if len(data) < 16 { | 
|  | 50 | +		return nil, fmt.Errorf("data too short for TLV format: got %d bytes, need at least 16", len(data)) | 
|  | 51 | +	} | 
|  | 52 | +	// parse TLV header | 
|  | 53 | +	header := TLVHeader{ | 
|  | 54 | +		Type:   data[0], | 
|  | 55 | +		Length: binary.BigEndian.Uint32(data[1:5]), | 
|  | 56 | +	} | 
|  | 57 | +	// test | 
|  | 58 | +	if header.Type != TLV_ORG_DST_ADDR_TYPE { | 
|  | 59 | +		return nil, fmt.Errorf("unexpected TLV type: got %#x, want %#x", header.Type, TLV_ORG_DST_ADDR_TYPE) | 
|  | 60 | +	} | 
|  | 61 | +	var tlvData TLVData | 
|  | 62 | +	var expectedMinSize int | 
|  | 63 | +	if header.Length == 6 { | 
|  | 64 | +		if len(data) < 16 { | 
|  | 65 | +			return nil, fmt.Errorf("IPv4 TLV data too short: got %d bytes, need at least 16", len(data)) | 
|  | 66 | +		} | 
|  | 67 | +		tlvData.IP = net.IPv4(data[5], data[6], data[7], data[8]) | 
|  | 68 | +		tlvData.Port = binary.BigEndian.Uint16(data[9:11]) | 
|  | 69 | +		expectedMinSize = 16 | 
|  | 70 | +	} else if header.Length == 18 { | 
|  | 71 | +		if len(data) < 28 { | 
|  | 72 | +			return nil, fmt.Errorf("IPv6 TLV data too short: got %d bytes, need at least 28", len(data)) | 
|  | 73 | +		} | 
|  | 74 | +		tlvData.IP = net.IP(data[5:21]) | 
|  | 75 | +		tlvData.Port = binary.BigEndian.Uint16(data[21:23]) | 
|  | 76 | +		expectedMinSize = 28 | 
|  | 77 | +	} else { | 
|  | 78 | +		return nil, fmt.Errorf("unsupported TLV length: %d (expected 6 for IPv4 or 18 for IPv6)", header.Length) | 
|  | 79 | +	} | 
|  | 80 | +	if len(data) < expectedMinSize { | 
|  | 81 | +		return nil, fmt.Errorf("data too short for end tag validation: got %d bytes, need at least %d", len(data), expectedMinSize) | 
|  | 82 | +	} | 
|  | 83 | +	endTag := data[expectedMinSize-5] | 
|  | 84 | +	if endTag != TLV_PAYLOAD_TYPE { | 
|  | 85 | +		return nil, fmt.Errorf("missing or wrong TLV end tag: got %#x, want %#x", endTag, TLV_PAYLOAD_TYPE) | 
|  | 86 | +	} | 
|  | 87 | +	endLength := binary.BigEndian.Uint32(data[expectedMinSize-4 : expectedMinSize]) | 
|  | 88 | +	if endLength != TLV_END_LENGTH { | 
|  | 89 | +		return nil, fmt.Errorf("unexpected TLV end length: got %#08x, want %#08x", endLength, TLV_END_LENGTH) | 
|  | 90 | +	} | 
|  | 91 | +	return &tlvData, nil | 
|  | 92 | +} | 
|  | 93 | + | 
|  | 94 | +// verify the integrity and correctness of the TLV message | 
|  | 95 | +func ValidateTLVMessage(t *testing.T, data []byte, expectedIP net.IP, expectedPort uint16) error { | 
|  | 96 | +	tlvData, err := ParseTLVMessage(data) | 
|  | 97 | +	if err != nil { | 
|  | 98 | +		return fmt.Errorf("failed to parse TLV message: %v", err) | 
|  | 99 | +	} | 
|  | 100 | +	if !tlvData.IP.Equal(expectedIP) { | 
|  | 101 | +		return fmt.Errorf("unexpected TLV IP: got %v, want %v", tlvData.IP, expectedIP) | 
|  | 102 | +	} | 
|  | 103 | +	if tlvData.Port != expectedPort { | 
|  | 104 | +		return fmt.Errorf("unexpected TLV port: got %d, want %d", tlvData.Port, expectedPort) | 
|  | 105 | +	} | 
|  | 106 | +	t.Logf("TLV message validation successful: IP=%v, Port=%d", tlvData.IP, tlvData.Port) | 
|  | 107 | +	return nil | 
|  | 108 | +} | 
0 commit comments