Skip to content

Instantly share code, notes, and snippets.

@lixin9311
Created April 21, 2024 15:35
Show Gist options
  • Save lixin9311/a7f9455a2802ce7260642b5658f61474 to your computer and use it in GitHub Desktop.
Save lixin9311/a7f9455a2802ce7260642b5658f61474 to your computer and use it in GitHub Desktop.
Convert Huawei OMCI debug output to pcap
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"log"
"os"
"strings"
"time"
)
const EthType = "88B5"
func main() {
data, err := os.ReadFile("b850.log")
if err != nil {
log.Fatal(err)
}
// split data by empty line
chunks := bytes.Split(data, []byte("\n\n"))
fmt.Println("Number of chunks:", len(chunks))
// pcap magic header
header := []byte{0xD4, 0xC3, 0xB2, 0xA1, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}
macOlt := "088701701701"
macOnt := "088788000000"
f, err := os.Create("output.pcap")
if err != nil {
log.Fatal(err)
}
defer f.Close()
f.Write(header)
for i, chunk := range chunks {
lines := strings.Split(string(chunk), "\n")
// first line: [1981-01-01 00:04:29.057952]OLT->ONT: Priority=1,SN=14596, Device ID=0xA
// parse the timestamp from the first line
timestampStr := lines[0][1:27]
// direction
sender := lines[0][28:31]
receiver := lines[0][33:36]
fmt.Println("Timestamp:", timestampStr)
fmt.Println(sender, "->", receiver)
// we do not need #2, #3 lines, or even #4 line
if strings.HasPrefix(string(lines[2]), "Operating Result") {
lines = lines[4:]
} else {
lines = lines[3:]
}
payload := strings.Join(lines, " ")
payload = strings.ReplaceAll(payload, " ", "")
fmt.Println("Payload:", payload)
ts, err := time.Parse("2006-01-02 15:04:05.999999", timestampStr)
if err != nil {
log.Fatal(err)
}
if sender == "OLT" {
writePayload(f, ts, macOlt, macOnt, payload)
} else {
writePayload(f, ts, macOnt, macOlt, payload)
}
_ = i
}
}
func writePayload(wr io.Writer, ts time.Time, sender, receiver, payload string) {
// write timestamp
if err := binary.Write(wr, binary.LittleEndian, int32(ts.Unix())); err != nil {
log.Fatal(err)
}
// write nanoseconds
if err := binary.Write(wr, binary.LittleEndian, int32(ts.Nanosecond()%1e9)); err != nil {
log.Fatal(err)
}
data := fromHex(sender)
data = append(data, fromHex(receiver)...)
data = append(data, fromHex(EthType)...)
data = append(data, fromHex(payload)...)
// write packet length
if err := binary.Write(wr, binary.LittleEndian, int32(len(data))); err != nil {
log.Fatal(err)
}
if err := binary.Write(wr, binary.LittleEndian, int32(len(data))); err != nil {
log.Fatal(err)
}
// write packet data
if _, err := wr.Write(data); err != nil {
log.Fatal(err)
}
}
func fromHex(str string) []byte {
b, err := hex.DecodeString(str)
if err != nil {
log.Fatal(err)
}
return b
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment