netlogtype.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package netlogtype defines types for network logging.
  4. package netlogtype
  5. import (
  6. "net/netip"
  7. "time"
  8. "tailscale.com/tailcfg"
  9. "tailscale.com/types/ipproto"
  10. )
  11. // TODO(joetsai): Remove "omitempty" if "omitzero" is ever supported in both
  12. // the v1 and v2 "json" packages.
  13. // Message is the log message that captures network traffic.
  14. type Message struct {
  15. NodeID tailcfg.StableNodeID `json:"nodeId" cbor:"0,keyasint"` // e.g., "n123456CNTRL"
  16. Start time.Time `json:"start" cbor:"12,keyasint"` // inclusive
  17. End time.Time `json:"end" cbor:"13,keyasint"` // inclusive
  18. VirtualTraffic []ConnectionCounts `json:"virtualTraffic,omitempty" cbor:"14,keyasint,omitempty"`
  19. SubnetTraffic []ConnectionCounts `json:"subnetTraffic,omitempty" cbor:"15,keyasint,omitempty"`
  20. ExitTraffic []ConnectionCounts `json:"exitTraffic,omitempty" cbor:"16,keyasint,omitempty"`
  21. PhysicalTraffic []ConnectionCounts `json:"physicalTraffic,omitempty" cbor:"17,keyasint,omitempty"`
  22. }
  23. const (
  24. messageJSON = `{"nodeId":"n0123456789abcdefCNTRL",` + maxJSONTimeRange + `,` + minJSONTraffic + `}`
  25. maxJSONTimeRange = `"start":` + maxJSONRFC3339 + `,"end":` + maxJSONRFC3339
  26. maxJSONRFC3339 = `"0001-01-01T00:00:00.000000000Z"`
  27. minJSONTraffic = `"virtualTraffic":{},"subnetTraffic":{},"exitTraffic":{},"physicalTraffic":{}`
  28. // MaxMessageJSONSize is the overhead size of Message when it is
  29. // serialized as JSON assuming that each traffic map is populated.
  30. MaxMessageJSONSize = len(messageJSON)
  31. maxJSONConnCounts = `{` + maxJSONConn + `,` + maxJSONCounts + `}`
  32. maxJSONConn = `"proto":` + maxJSONProto + `,"src":` + maxJSONAddrPort + `,"dst":` + maxJSONAddrPort
  33. maxJSONProto = `255`
  34. maxJSONAddrPort = `"[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"`
  35. maxJSONCounts = `"txPkts":` + maxJSONCount + `,"txBytes":` + maxJSONCount + `,"rxPkts":` + maxJSONCount + `,"rxBytes":` + maxJSONCount
  36. maxJSONCount = `18446744073709551615`
  37. // MaxConnectionCountsJSONSize is the maximum size of a ConnectionCounts
  38. // when it is serialized as JSON, assuming no superfluous whitespace.
  39. // It does not include the trailing comma that often appears when
  40. // this object is nested within an array.
  41. // It assumes that netip.Addr never has IPv6 zones.
  42. MaxConnectionCountsJSONSize = len(maxJSONConnCounts)
  43. maxCBORConnCounts = "\xbf" + maxCBORConn + maxCBORCounts + "\xff"
  44. maxCBORConn = "\x00" + maxCBORProto + "\x01" + maxCBORAddrPort + "\x02" + maxCBORAddrPort
  45. maxCBORProto = "\x18\xff"
  46. maxCBORAddrPort = "\x52\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
  47. maxCBORCounts = "\x0c" + maxCBORCount + "\x0d" + maxCBORCount + "\x0e" + maxCBORCount + "\x0f" + maxCBORCount
  48. maxCBORCount = "\x1b\xff\xff\xff\xff\xff\xff\xff\xff"
  49. // MaxConnectionCountsCBORSize is the maximum size of a ConnectionCounts
  50. // when it is serialized as CBOR.
  51. // It assumes that netip.Addr never has IPv6 zones.
  52. MaxConnectionCountsCBORSize = len(maxCBORConnCounts)
  53. )
  54. // ConnectionCounts is a flattened struct of both a connection and counts.
  55. type ConnectionCounts struct {
  56. Connection
  57. Counts
  58. }
  59. // Connection is a 5-tuple of proto, source and destination IP and port.
  60. type Connection struct {
  61. Proto ipproto.Proto `json:"proto,omitzero,omitempty" cbor:"0,keyasint,omitempty"`
  62. Src netip.AddrPort `json:"src,omitzero,omitempty" cbor:"1,keyasint,omitempty"`
  63. Dst netip.AddrPort `json:"dst,omitzero,omitempty" cbor:"2,keyasint,omitempty"`
  64. }
  65. func (c Connection) IsZero() bool { return c == Connection{} }
  66. // Counts are statistics about a particular connection.
  67. type Counts struct {
  68. TxPackets uint64 `json:"txPkts,omitzero,omitempty" cbor:"12,keyasint,omitempty"`
  69. TxBytes uint64 `json:"txBytes,omitzero,omitempty" cbor:"13,keyasint,omitempty"`
  70. RxPackets uint64 `json:"rxPkts,omitzero,omitempty" cbor:"14,keyasint,omitempty"`
  71. RxBytes uint64 `json:"rxBytes,omitzero,omitempty" cbor:"15,keyasint,omitempty"`
  72. }
  73. func (c Counts) IsZero() bool { return c == Counts{} }
  74. // Add adds the counts from both c1 and c2.
  75. func (c1 Counts) Add(c2 Counts) Counts {
  76. c1.TxPackets += c2.TxPackets
  77. c1.TxBytes += c2.TxBytes
  78. c1.RxPackets += c2.RxPackets
  79. c1.RxBytes += c2.RxBytes
  80. return c1
  81. }