From 94a24ea1d229630a6b83f250af39d16f432a475b Mon Sep 17 00:00:00 2001 From: Patrick Cullen Date: Tue, 15 Oct 2024 03:39:33 -0700 Subject: [PATCH] stop panics when signaling messages received by ziffy receiver from ziffy sender Summary: Ziffy running in receive mode did not process incoming signaling messages (the tool was assuming Ziffy packets being sent were either SYNC or DELAY_REQ) ``` INFO[0000] listening on port 319 for PTP EVENT packets (SYNC/DELAY_REQ) with ZiffyHexa signature. Sending back the packets as icmp panic: interface conversion: protocol.Packet is *protocol.Announce, not *protocol.SyncDelayReq goroutine 54 [running]: github.com/facebook/time/cmd/ziffy/node.parseSyncPacket({0x2d9910, 0xc000304dc0}) fbcode/time/cmd/ziffy/node/receiver.go:165 +0x1c5 github.com/facebook/time/cmd/ziffy/node.(*Receiver).handlePacket(0xc0001321b0, {0x2d9910, 0xc000304dc0}) fbcode/time/cmd/ziffy/node/receiver.go:104 +0x78 created by github.com/facebook/time/cmd/ziffy/node.(*Receiver).Start in goroutine 1 fbcode/time/cmd/ziffy/node/receiver.go:74 +0x392 [root@twshared16917.02.rva6 ~]# dnf install -y fb-ziffy && systemctl stop sptp && ziffy -mode receiver ; systemctl start sptp Last metadata expiration check: 0:00:37 ago on Thu 10 Oct 2024 13:36:26. Package fb-ziffy-20241009-213047.x86_64 is already installed. Dependencies resolved. ``` Reviewed By: abulimov Differential Revision: D64358486 fbshipit-source-id: dfaa474a1d7c8b938c1b173bc5d43cc94849b541 --- cmd/ziffy/node/receiver.go | 6 +++++- cmd/ziffy/node/receiver_test.go | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cmd/ziffy/node/receiver.go b/cmd/ziffy/node/receiver.go index d5ca6588..649b6b9b 100644 --- a/cmd/ziffy/node/receiver.go +++ b/cmd/ziffy/node/receiver.go @@ -148,6 +148,7 @@ func (r *Receiver) sendResponse(sourceIP string, rawPacket gopacket.Packet) erro return nil } +// parseSyncPacket parses SYNC/DELAY_REQ packets and returns the packet, source IP and source port func parseSyncPacket(packet gopacket.Packet) (*ptp.SyncDelayReq, string, string, error) { ipHeader, ok := packet.NetworkLayer().(*layers.IPv6) if !ok { @@ -160,7 +161,10 @@ func parseSyncPacket(packet gopacket.Packet) (*ptp.SyncDelayReq, string, string, ptpPacket, err := ptp.DecodePacket(packet.ApplicationLayer().Payload()) if err != nil { - return nil, "", "", fmt.Errorf("unable to decode ptp packet: %w", err) + return nil, "", "", fmt.Errorf("unable to decode PTP packet: %w", err) + } + if ptpPacket.MessageType() != ptp.MessageSync && ptpPacket.MessageType() != ptp.MessageDelayReq { + return nil, "", "", fmt.Errorf("not parsing %v: not a SYNC/DELAY_REQ packet", ptpPacket.MessageType().String()) } return ptpPacket.(*ptp.SyncDelayReq), ipHeader.SrcIP.String(), strconv.Itoa(int(udpHeader.SrcPort)), nil } diff --git a/cmd/ziffy/node/receiver_test.go b/cmd/ziffy/node/receiver_test.go index c28ee92a..6ce0decb 100644 --- a/cmd/ziffy/node/receiver_test.go +++ b/cmd/ziffy/node/receiver_test.go @@ -21,13 +21,14 @@ import ( "sync" "testing" + ptp "github.com/facebook/time/ptp/protocol" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/stretchr/testify/require" ) -// rawPTP packet received from sender -var rawPTP = []byte{ +// raw PTP packet (SYNC) received from sender +var syncPTPPacket = []byte{ 0xb8, 0xce, 0xf6, 0x61, 0x00, 0x80, 0xc2, 0x18, 0x50, 0x09, 0xca, 0x4e, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x36, 0x11, 0x01, 0xfa, 0xce, 0xdb, 0x00, 0xfa, 0xce, 0x12, 0x02, 0xfa, 0xce, 0x00, 0x00, 0xfa, 0xce, 0x00, 0xff, 0xfa, 0xce, 0xdb, 0x00, 0xfa, 0xce, 0x26, 0x08, 0xfa, 0xce, @@ -37,6 +38,17 @@ var rawPTP = []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } +// raw PTP packet (Signaling) received from sender +var signalPTPPacket = []byte{ + 0xb8, 0xce, 0xf6, 0x61, 0x00, 0x80, 0xc2, 0x18, 0x50, 0x09, 0xca, 0x4e, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x36, 0x11, 0x01, 0xfa, 0xce, 0xdb, 0x00, 0xfa, 0xce, 0x14, 0x20, 0xfa, 0xce, + 0x00, 0x00, 0xfa, 0xce, 0x00, 0xff, 0xfa, 0xce, 0xdb, 0x00, 0xfa, 0xce, 0x26, 0x08, 0xfa, 0xce, + 0x00, 0x00, 0xfa, 0xce, 0x00, 0xff, 0xd2, 0xfa, 0x01, 0x3f, 0x00, 0x36, 0x51, 0xeb, 0x0c, 0x02, + 0x00, 0x2c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x57, 0x10, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xfa, 0x00, 0x06, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +} + func TestIncRunningHandlers(t *testing.T) { r := Receiver{ Config: &Config{PTPRecvHandlers: 2}, @@ -68,7 +80,7 @@ func TestDecRunningHandlers(t *testing.T) { } func TestHandlePacket(t *testing.T) { - packet := gopacket.NewPacket(rawPTP, layers.LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) + packet := gopacket.NewPacket(syncPTPPacket, layers.LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) r := Receiver{ Config: &Config{PTPRecvHandlers: 3}, @@ -86,13 +98,21 @@ func TestHandlePacket(t *testing.T) { require.Equal(t, true, r.incRunningHandlers()) } -func TestParseSyncPacket(t *testing.T) { - packet := gopacket.NewPacket(rawPTP, layers.LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) +func TestParseSyncPacketOnSyncPacket(t *testing.T) { + packet := gopacket.NewPacket(syncPTPPacket, layers.LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) ptpPacket, srcIP, srcPort, err := parseSyncPacket(packet) require.Nil(t, err) require.Equal(t, uint8(ZiffyHexa), ptpPacket.ControlField) + require.Equal(t, ptp.MessageSync, ptpPacket.MessageType()) require.Equal(t, "face:db00:face:1202:face:0:face:ff", srcIP) require.Equal(t, strconv.Itoa(32770), srcPort) require.Equal(t, uint16(32770), ptpPacket.SourcePortIdentity.PortNumber) } + +func TestParseSyncPacketOnSignalPacket(t *testing.T) { + packet := gopacket.NewPacket(signalPTPPacket, layers.LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) + + _, _, _, err := parseSyncPacket(packet) + require.NotNil(t, err) +}