diff --git a/go.mod b/go.mod
index 315f432ba19..e0b698ab4eb 100644
--- a/go.mod
+++ b/go.mod
@@ -36,8 +36,8 @@ require (
github.com/spf13/viper v1.19.0
github.com/sryoya/protorand v0.0.0-20240429201223-e7440656b2a4
github.com/stretchr/testify v1.9.0
- github.com/tidwall/gjson v1.17.0
- github.com/vishvananda/netlink v1.2.1-beta.2.0.20240524165444-4d4ba1473f21
+ github.com/tidwall/gjson v1.17.3
+ github.com/vishvananda/netlink v1.2.1
go.uber.org/atomic v1.11.0
go.uber.org/multierr v1.11.0
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
diff --git a/go.sum b/go.sum
index c3a4ad9af96..50dca6c376b 100644
--- a/go.sum
+++ b/go.sum
@@ -540,8 +540,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
-github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
+github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@@ -552,9 +552,8 @@ github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7Am
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
-github.com/vishvananda/netlink v1.2.1-beta.2.0.20240524165444-4d4ba1473f21 h1:tcHUxOT8j/R+0S+A1j8D2InqguXFNxAiij+8QFOlX7Y=
-github.com/vishvananda/netlink v1.2.1-beta.2.0.20240524165444-4d4ba1473f21/go.mod h1:whJevzBpTrid75eZy99s3DqCmy05NfibNaF2Ol5Ox5A=
-github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vishvananda/netlink v1.2.1 h1:pfLv/qlJUwOTPvtWREA7c3PI4u81YkqZw1DYhI2HmLA=
+github.com/vishvananda/netlink v1.2.1/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY=
@@ -677,7 +676,6 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/tidwall/gjson/README.md b/vendor/github.com/tidwall/gjson/README.md
index 96b2e4dc330..7701cae4366 100644
--- a/vendor/github.com/tidwall/gjson/README.md
+++ b/vendor/github.com/tidwall/gjson/README.md
@@ -1,7 +1,9 @@
-
+
+
+
+
+
diff --git a/vendor/github.com/tidwall/gjson/SYNTAX.md b/vendor/github.com/tidwall/gjson/SYNTAX.md
index 6721d7f5143..a3f0fac2380 100644
--- a/vendor/github.com/tidwall/gjson/SYNTAX.md
+++ b/vendor/github.com/tidwall/gjson/SYNTAX.md
@@ -1,6 +1,6 @@
# GJSON Path Syntax
-A GJSON Path is a text string syntax that describes a search pattern for quickly retreiving values from a JSON payload.
+A GJSON Path is a text string syntax that describes a search pattern for quickly retrieving values from a JSON payload.
This document is designed to explain the structure of a GJSON Path through examples.
@@ -15,12 +15,12 @@ This document is designed to explain the structure of a GJSON Path through examp
- [Multipaths](#multipaths)
- [Literals](#literals)
-The definitive implemenation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
+The definitive implementation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online.
## Path structure
-A GJSON Path is intended to be easily expressed as a series of components seperated by a `.` character.
+A GJSON Path is intended to be easily expressed as a series of components separated by a `.` character.
Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, `!`, and `?`.
@@ -46,7 +46,7 @@ The following GJSON Paths evaluate to the accompanying values.
### Basic
-In many cases you'll just want to retreive values by object name or array index.
+In many cases you'll just want to retrieve values by object name or array index.
```go
name.last "Anderson"
diff --git a/vendor/github.com/tidwall/gjson/gjson.go b/vendor/github.com/tidwall/gjson/gjson.go
index 79498250aec..779fe617fe2 100644
--- a/vendor/github.com/tidwall/gjson/gjson.go
+++ b/vendor/github.com/tidwall/gjson/gjson.go
@@ -1252,7 +1252,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
}
// matchLimit will limit the complexity of the match operation to avoid ReDos
-// attacks from arbritary inputs.
+// attacks from arbitrary inputs.
// See the github.com/tidwall/match.MatchLimit function for more information.
func matchLimit(str, pattern string) bool {
matched, _ := match.MatchLimit(str, pattern, 10000)
@@ -1917,6 +1917,16 @@ func appendHex16(dst []byte, x uint16) []byte {
)
}
+// DisableEscapeHTML will disable the automatic escaping of certain
+// "problamatic" HTML characters when encoding to JSON.
+// These character include '>', '<' and '&', which get escaped to \u003e,
+// \u0026, and \u003c respectively.
+//
+// This is a global flag and will affect all further gjson operations.
+// Ideally, if used, it should be set one time before other gjson functions
+// are called.
+var DisableEscapeHTML = false
+
// AppendJSONString is a convenience function that converts the provided string
// to a valid JSON string and appends it to dst.
func AppendJSONString(dst []byte, s string) []byte {
@@ -1926,6 +1936,10 @@ func AppendJSONString(dst []byte, s string) []byte {
if s[i] < ' ' {
dst = append(dst, '\\')
switch s[i] {
+ case '\b':
+ dst = append(dst, 'b')
+ case '\f':
+ dst = append(dst, 'f')
case '\n':
dst = append(dst, 'n')
case '\r':
@@ -1936,7 +1950,8 @@ func AppendJSONString(dst []byte, s string) []byte {
dst = append(dst, 'u')
dst = appendHex16(dst, uint16(s[i]))
}
- } else if s[i] == '>' || s[i] == '<' || s[i] == '&' {
+ } else if !DisableEscapeHTML &&
+ (s[i] == '>' || s[i] == '<' || s[i] == '&') {
dst = append(dst, '\\', 'u')
dst = appendHex16(dst, uint16(s[i]))
} else if s[i] == '\\' {
@@ -2190,7 +2205,7 @@ func unescape(json string) string {
}
// Less return true if a token is less than another token.
-// The caseSensitive paramater is used when the tokens are Strings.
+// The caseSensitive parameter is used when the tokens are Strings.
// The order when comparing two different type is:
//
// Null < False < Number < String < True < JSON
@@ -3349,7 +3364,7 @@ func (t Result) Path(json string) string {
goto fail
}
if !strings.HasPrefix(json[t.Index:], t.Raw) {
- // Result is not at the JSON index as exepcted.
+ // Result is not at the JSON index as expected.
goto fail
}
for ; i >= 0; i-- {
diff --git a/vendor/github.com/tidwall/gjson/logo.png b/vendor/github.com/tidwall/gjson/logo.png
deleted file mode 100644
index 17a8bbe9d65..00000000000
Binary files a/vendor/github.com/tidwall/gjson/logo.png and /dev/null differ
diff --git a/vendor/github.com/vishvananda/netlink/.gitignore b/vendor/github.com/vishvananda/netlink/.gitignore
index 9f11b755a17..66f8fb50272 100644
--- a/vendor/github.com/vishvananda/netlink/.gitignore
+++ b/vendor/github.com/vishvananda/netlink/.gitignore
@@ -1 +1,2 @@
.idea/
+.vscode/
diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
index eaa77e9c87c..d2cd68affe8 100644
--- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
@@ -55,10 +55,28 @@ func ConntrackTableFlush(table ConntrackTableType) error {
return pkgHandle.ConntrackTableFlush(table)
}
+// ConntrackCreate creates a new conntrack flow in the desired table
+// conntrack -I [table] Create a conntrack or expectation
+func ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
+ return pkgHandle.ConntrackCreate(table, family, flow)
+}
+
+// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
+// conntrack -U [table] Update a conntrack
+func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
+ return pkgHandle.ConntrackUpdate(table, family, flow)
+}
+
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
// conntrack -D [table] parameters Delete conntrack or expectation
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
- return pkgHandle.ConntrackDeleteFilter(table, family, filter)
+ return pkgHandle.ConntrackDeleteFilters(table, family, filter)
+}
+
+// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
+// conntrack -D [table] parameters Delete conntrack or expectation
+func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
+ return pkgHandle.ConntrackDeleteFilters(table, family, filters...)
}
// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed
@@ -87,9 +105,43 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
return err
}
-// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed
+// ConntrackCreate creates a new conntrack flow in the desired table using the handle
+// conntrack -I [table] Create a conntrack or expectation
+func (h *Handle) ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
+ req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_CREATE)
+ attr, err := flow.toNlData()
+ if err != nil {
+ return err
+ }
+
+ for _, a := range attr {
+ req.AddData(a)
+ }
+
+ _, err = req.Execute(unix.NETLINK_NETFILTER, 0)
+ return err
+}
+
+// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
+// conntrack -U [table] Update a conntrack
+func (h *Handle) ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
+ req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_REPLACE)
+ attr, err := flow.toNlData()
+ if err != nil {
+ return err
+ }
+
+ for _, a := range attr {
+ req.AddData(a)
+ }
+
+ _, err = req.Execute(unix.NETLINK_NETFILTER, 0)
+ return err
+}
+
+// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
// conntrack -D [table] parameters Delete conntrack or expectation
-func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
+func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
res, err := h.dumpConntrackTable(table, family)
if err != nil {
return 0, err
@@ -98,12 +150,16 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
var matched uint
for _, dataRaw := range res {
flow := parseRawData(dataRaw)
- if match := filter.MatchConntrackFlow(flow); match {
- req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
- // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
- req2.AddRawData(dataRaw[4:])
- req2.Execute(unix.NETLINK_NETFILTER, 0)
- matched++
+ for _, filter := range filters {
+ if match := filter.MatchConntrackFlow(flow); match {
+ req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
+ // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
+ req2.AddRawData(dataRaw[4:])
+ req2.Execute(unix.NETLINK_NETFILTER, 0)
+ matched++
+ // flow is already deleted, no need to match on other filters and continue to the next flow.
+ break
+ }
}
}
@@ -128,10 +184,44 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
return req.Execute(unix.NETLINK_NETFILTER, 0)
}
+// ProtoInfo wraps an L4-protocol structure - roughly corresponds to the
+// __nfct_protoinfo union found in libnetfilter_conntrack/include/internal/object.h.
+// Currently, only protocol names, and TCP state is supported.
+type ProtoInfo interface {
+ Protocol() string
+}
+
+// ProtoInfoTCP corresponds to the `tcp` struct of the __nfct_protoinfo union.
+// Only TCP state is currently supported.
+type ProtoInfoTCP struct {
+ State uint8
+}
+// Protocol returns "tcp".
+func (*ProtoInfoTCP) Protocol() string {return "tcp"}
+func (p *ProtoInfoTCP) toNlData() ([]*nl.RtAttr, error) {
+ ctProtoInfo := nl.NewRtAttr(unix.NLA_F_NESTED | nl.CTA_PROTOINFO, []byte{})
+ ctProtoInfoTCP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_PROTOINFO_TCP, []byte{})
+ ctProtoInfoTCPState := nl.NewRtAttr(nl.CTA_PROTOINFO_TCP_STATE, nl.Uint8Attr(p.State))
+ ctProtoInfoTCP.AddChild(ctProtoInfoTCPState)
+ ctProtoInfo.AddChild(ctProtoInfoTCP)
+
+ return []*nl.RtAttr{ctProtoInfo}, nil
+}
+
+// ProtoInfoSCTP only supports the protocol name.
+type ProtoInfoSCTP struct {}
+// Protocol returns "sctp".
+func (*ProtoInfoSCTP) Protocol() string {return "sctp"}
+
+// ProtoInfoDCCP only supports the protocol name.
+type ProtoInfoDCCP struct {}
+// Protocol returns "dccp".
+func (*ProtoInfoDCCP) Protocol() string {return "dccp"}
+
// The full conntrack flow structure is very complicated and can be found in the file:
// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h
// For the time being, the structure below allows to parse and extract the base information of a flow
-type ipTuple struct {
+type IPTuple struct {
Bytes uint64
DstIP net.IP
DstPort uint16
@@ -141,16 +231,49 @@ type ipTuple struct {
SrcPort uint16
}
+// toNlData generates the inner fields of a nested tuple netlink datastructure
+// does not generate the "nested"-flagged outer message.
+func (t *IPTuple) toNlData(family uint8) ([]*nl.RtAttr, error) {
+
+ var srcIPsFlag, dstIPsFlag int
+ if family == nl.FAMILY_V4 {
+ srcIPsFlag = nl.CTA_IP_V4_SRC
+ dstIPsFlag = nl.CTA_IP_V4_DST
+ } else if family == nl.FAMILY_V6 {
+ srcIPsFlag = nl.CTA_IP_V6_SRC
+ dstIPsFlag = nl.CTA_IP_V6_DST
+ } else {
+ return []*nl.RtAttr{}, fmt.Errorf("couldn't generate netlink message for tuple due to unrecognized FamilyType '%d'", family)
+ }
+
+ ctTupleIP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_IP, nil)
+ ctTupleIPSrc := nl.NewRtAttr(srcIPsFlag, t.SrcIP)
+ ctTupleIP.AddChild(ctTupleIPSrc)
+ ctTupleIPDst := nl.NewRtAttr(dstIPsFlag, t.DstIP)
+ ctTupleIP.AddChild(ctTupleIPDst)
+
+ ctTupleProto := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_PROTO, nil)
+ ctTupleProtoNum := nl.NewRtAttr(nl.CTA_PROTO_NUM, []byte{t.Protocol})
+ ctTupleProto.AddChild(ctTupleProtoNum)
+ ctTupleProtoSrcPort := nl.NewRtAttr(nl.CTA_PROTO_SRC_PORT, nl.BEUint16Attr(t.SrcPort))
+ ctTupleProto.AddChild(ctTupleProtoSrcPort)
+ ctTupleProtoDstPort := nl.NewRtAttr(nl.CTA_PROTO_DST_PORT, nl.BEUint16Attr(t.DstPort))
+ ctTupleProto.AddChild(ctTupleProtoDstPort, )
+
+ return []*nl.RtAttr{ctTupleIP, ctTupleProto}, nil
+}
+
type ConntrackFlow struct {
FamilyType uint8
- Forward ipTuple
- Reverse ipTuple
+ Forward IPTuple
+ Reverse IPTuple
Mark uint32
Zone uint16
TimeStart uint64
TimeStop uint64
TimeOut uint32
Labels []byte
+ ProtoInfo ProtoInfo
}
func (s *ConntrackFlow) String() string {
@@ -175,6 +298,85 @@ func (s *ConntrackFlow) String() string {
return res
}
+// toNlData generates netlink messages representing the flow.
+func (s *ConntrackFlow) toNlData() ([]*nl.RtAttr, error) {
+ var payload []*nl.RtAttr
+ // The message structure is built as follows:
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+
+ // CTA_TUPLE_ORIG
+ ctTupleOrig := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_ORIG, nil)
+ forwardFlowAttrs, err := s.Forward.toNlData(s.FamilyType)
+ if err != nil {
+ return nil, fmt.Errorf("couldn't generate netlink data for conntrack forward flow: %w", err)
+ }
+ for _, a := range forwardFlowAttrs {
+ ctTupleOrig.AddChild(a)
+ }
+
+ // CTA_TUPLE_REPLY
+ ctTupleReply := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_REPLY, nil)
+ reverseFlowAttrs, err := s.Reverse.toNlData(s.FamilyType)
+ if err != nil {
+ return nil, fmt.Errorf("couldn't generate netlink data for conntrack reverse flow: %w", err)
+ }
+ for _, a := range reverseFlowAttrs {
+ ctTupleReply.AddChild(a)
+ }
+
+ ctMark := nl.NewRtAttr(nl.CTA_MARK, nl.BEUint32Attr(s.Mark))
+ ctTimeout := nl.NewRtAttr(nl.CTA_TIMEOUT, nl.BEUint32Attr(s.TimeOut))
+
+ payload = append(payload, ctTupleOrig, ctTupleReply, ctMark, ctTimeout)
+
+ if s.ProtoInfo != nil {
+ switch p := s.ProtoInfo.(type) {
+ case *ProtoInfoTCP:
+ attrs, err := p.toNlData()
+ if err != nil {
+ return nil, fmt.Errorf("couldn't generate netlink data for conntrack flow's TCP protoinfo: %w", err)
+ }
+ payload = append(payload, attrs...)
+ default:
+ return nil, errors.New("couldn't generate netlink data for conntrack: field 'ProtoInfo' only supports TCP or nil")
+ }
+ }
+
+ return payload, nil
+}
+
// This method parse the ip tuple structure
// The message structure is the following:
//
@@ -182,7 +384,7 @@ func (s *ConntrackFlow) String() string {
//
//
//
-func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
+func parseIpTuple(reader *bytes.Reader, tpl *IPTuple) uint8 {
for i := 0; i < 2; i++ {
_, t, _, v := parseNfAttrTLV(reader)
switch t {
@@ -201,7 +403,7 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
tpl.Protocol = uint8(v[0])
}
// We only parse TCP & UDP headers. Skip the others.
- if tpl.Protocol != 6 && tpl.Protocol != 17 {
+ if tpl.Protocol != unix.IPPROTO_TCP && tpl.Protocol != unix.IPPROTO_UDP {
// skip the rest
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
reader.Seek(int64(bytesRemaining), seekCurrent)
@@ -250,9 +452,13 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
return isNested, attrType, len
}
-func skipNfAttrValue(r *bytes.Reader, len uint16) {
+// skipNfAttrValue seeks `r` past attr of length `len`.
+// Maintains buffer alignment.
+// Returns length of the seek performed.
+func skipNfAttrValue(r *bytes.Reader, len uint16) uint16 {
len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
r.Seek(int64(len), seekCurrent)
+ return len
}
func parseBERaw16(r *bytes.Reader, v *uint16) {
@@ -267,6 +473,10 @@ func parseBERaw64(r *bytes.Reader, v *uint64) {
binary.Read(r, binary.BigEndian, v)
}
+func parseRaw32(r *bytes.Reader, v *uint32) {
+ binary.Read(r, nl.NativeEndian(), v)
+}
+
func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
for i := 0; i < 2; i++ {
switch _, t, _ := parseNfAttrTL(r); t {
@@ -306,6 +516,60 @@ func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
}
+func parseProtoInfoTCPState(r *bytes.Reader) (s uint8) {
+ binary.Read(r, binary.BigEndian, &s)
+ r.Seek(nl.SizeofNfattr - 1, seekCurrent)
+ return s
+}
+
+// parseProtoInfoTCP reads the entire nested protoinfo structure, but only parses the state attr.
+func parseProtoInfoTCP(r *bytes.Reader, attrLen uint16) (*ProtoInfoTCP) {
+ p := new(ProtoInfoTCP)
+ bytesRead := 0
+ for bytesRead < int(attrLen) {
+ _, t, l := parseNfAttrTL(r)
+ bytesRead += nl.SizeofNfattr
+
+ switch t {
+ case nl.CTA_PROTOINFO_TCP_STATE:
+ p.State = parseProtoInfoTCPState(r)
+ bytesRead += nl.SizeofNfattr
+ default:
+ bytesRead += int(skipNfAttrValue(r, l))
+ }
+ }
+
+ return p
+}
+
+func parseProtoInfo(r *bytes.Reader, attrLen uint16) (p ProtoInfo) {
+ bytesRead := 0
+ for bytesRead < int(attrLen) {
+ _, t, l := parseNfAttrTL(r)
+ bytesRead += nl.SizeofNfattr
+
+ switch t {
+ case nl.CTA_PROTOINFO_TCP:
+ p = parseProtoInfoTCP(r, l)
+ bytesRead += int(l)
+ // No inner fields of DCCP / SCTP currently supported.
+ case nl.CTA_PROTOINFO_DCCP:
+ p = new(ProtoInfoDCCP)
+ skipped := skipNfAttrValue(r, l)
+ bytesRead += int(skipped)
+ case nl.CTA_PROTOINFO_SCTP:
+ p = new(ProtoInfoSCTP)
+ skipped := skipNfAttrValue(r, l)
+ bytesRead += int(skipped)
+ default:
+ skipped := skipNfAttrValue(r, l)
+ bytesRead += int(skipped)
+ }
+ }
+
+ return p
+}
+
func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
parseBERaw32(r, &ttimeout)
return
@@ -365,7 +629,7 @@ func parseRawData(data []byte) *ConntrackFlow {
case nl.CTA_TIMESTAMP:
s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
case nl.CTA_PROTOINFO:
- skipNfAttrValue(reader, l)
+ s.ProtoInfo = parseProtoInfo(reader, l)
default:
skipNfAttrValue(reader, l)
}
@@ -373,11 +637,11 @@ func parseRawData(data []byte) *ConntrackFlow {
switch t {
case nl.CTA_MARK:
s.Mark = parseConnectionMark(reader)
- case nl.CTA_LABELS:
+ case nl.CTA_LABELS:
s.Labels = parseConnectionLabels(reader)
case nl.CTA_TIMEOUT:
s.TimeOut = parseTimeOut(reader)
- case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
+ case nl.CTA_ID, nl.CTA_STATUS, nl.CTA_USE:
skipNfAttrValue(reader, l)
case nl.CTA_ZONE:
s.Zone = parseConnectionZone(reader)
diff --git a/vendor/github.com/vishvananda/netlink/inet_diag.go b/vendor/github.com/vishvananda/netlink/inet_diag.go
index a483ee1a1d5..2904d964282 100644
--- a/vendor/github.com/vishvananda/netlink/inet_diag.go
+++ b/vendor/github.com/vishvananda/netlink/inet_diag.go
@@ -21,6 +21,10 @@ const (
INET_DIAG_BBRINFO
INET_DIAG_CLASS_ID
INET_DIAG_MD5SIG
+ INET_DIAG_ULP_INFO
+ INET_DIAG_SK_BPF_STORAGES
+ INET_DIAG_CGROUP_ID
+ INET_DIAG_SOCKOPT
INET_DIAG_MAX
)
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index 28780d11845..f820cdb678d 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -274,6 +274,7 @@ type Bridge struct {
HelloTime *uint32
VlanFiltering *bool
VlanDefaultPVID *uint16
+ GroupFwdMask *uint16
}
func (bridge *Bridge) Attrs() *LinkAttrs {
@@ -317,6 +318,9 @@ type Macvlan struct {
// MACAddrs is only populated for Macvlan SOURCE links
MACAddrs []net.HardwareAddr
+
+ BCQueueLen uint32
+ UsedBCQueueLen uint32
}
func (macvlan *Macvlan) Attrs() *LinkAttrs {
@@ -752,6 +756,7 @@ const (
BOND_XMIT_HASH_POLICY_LAYER2_3
BOND_XMIT_HASH_POLICY_ENCAP2_3
BOND_XMIT_HASH_POLICY_ENCAP3_4
+ BOND_XMIT_HASH_POLICY_VLAN_SRCMAC
BOND_XMIT_HASH_POLICY_UNKNOWN
)
@@ -761,6 +766,7 @@ var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
+ BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac",
}
var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
"layer2": BOND_XMIT_HASH_POLICY_LAYER2,
@@ -768,6 +774,7 @@ var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
+ "vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC,
}
// BondLacpRate type
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index 505d92d6996..d713612a907 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -1733,15 +1733,9 @@ func (h *Handle) linkModify(link Link, flags int) error {
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
case *Macvlan:
- if link.Mode != MACVLAN_MODE_DEFAULT {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
- }
+ addMacvlanAttrs(link, linkInfo)
case *Macvtap:
- if link.Mode != MACVLAN_MODE_DEFAULT {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
- }
+ addMacvtapAttrs(link, linkInfo)
case *Geneve:
addGeneveAttrs(link, linkInfo)
case *Gretap:
@@ -1975,9 +1969,6 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.Flags = linkFlags(msg.Flags)
base.EncapType = msg.EncapType()
base.NetNsID = -1
- if msg.Flags&unix.IFF_PROMISC != 0 {
- base.Promisc = 1
- }
if msg.Flags&unix.IFF_ALLMULTI != 0 {
base.Allmulti = 1
}
@@ -2164,6 +2155,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.Name = string(attr.Value[:len(attr.Value)-1])
case unix.IFLA_MTU:
base.MTU = int(native.Uint32(attr.Value[0:4]))
+ case unix.IFLA_PROMISCUITY:
+ base.Promisc = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_LINK:
base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_MASTER:
@@ -2494,6 +2487,16 @@ func (h *Handle) LinkSetGuard(link Link, mode bool) error {
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
}
+// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
+func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
+ return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask)
+}
+
+// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
+func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
+ return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK)
+}
+
func LinkSetFastLeave(link Link, mode bool) error {
return pkgHandle.LinkSetFastLeave(link, mode)
}
@@ -2558,7 +2561,7 @@ func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error {
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS)
}
-func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
+func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
@@ -2568,7 +2571,7 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
req.AddData(msg)
br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
- br.AddRtAttr(attr, boolToByte(mode))
+ br.AddRtAttr(attr, val)
req.AddData(br)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
if err != nil {
@@ -2576,6 +2579,9 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
}
return nil
}
+func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
+ return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr)
+}
// LinkSetTxQLen sets the transaction queue length for the link.
// Equivalent to: `ip link set $link txqlen $qlen`
@@ -2941,11 +2947,30 @@ func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) {
+ addMacvlanAttrs(&macvtap.Macvlan, linkInfo)
+}
+
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
macv := link.(*Macvtap)
parseMacvlanData(&macv.Macvlan, data)
}
+func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) {
+ var data *nl.RtAttr
+
+ if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 {
+ data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ }
+
+ if macvlan.Mode != MACVLAN_MODE_DEFAULT {
+ data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode]))
+ }
+ if macvlan.BCQueueLen > 0 {
+ data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen))
+ }
+}
+
func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
macv := link.(*Macvlan)
for _, datum := range data {
@@ -2973,6 +2998,10 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
for _, macDatum := range macs {
macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6]))
}
+ case nl.IFLA_MACVLAN_BC_QUEUE_LEN:
+ macv.BCQueueLen = native.Uint32(datum.Value[0:4])
+ case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED:
+ macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4])
}
}
}
@@ -3541,6 +3570,9 @@ func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
if bridge.VlanDefaultPVID != nil {
data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID))
}
+ if bridge.GroupFwdMask != nil {
+ data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask))
+ }
}
func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
@@ -3562,6 +3594,9 @@ func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BR_VLAN_DEFAULT_PVID:
vlanDefaultPVID := native.Uint16(datum.Value[0:2])
br.VlanDefaultPVID = &vlanDefaultPVID
+ case nl.IFLA_BR_GROUP_FWD_MASK:
+ mask := native.Uint16(datum.Value[0:2])
+ br.GroupFwdMask = &mask
}
}
}
@@ -3686,8 +3721,7 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
-// LinkSetBondSlave add slave to bond link via ioctl interface.
-func LinkSetBondSlave(link Link, master *Bond) error {
+func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
fd, err := getSocketUDP()
if err != nil {
return err
@@ -3695,10 +3729,38 @@ func LinkSetBondSlave(link Link, master *Bond) error {
defer syscall.Close(fd)
ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
-
- _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq)))
+ _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
- return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno)
+ return fmt.Errorf("errno=%v", errno)
+ }
+ return nil
+}
+
+// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
+//
+// Multiple calls keeps the status unchanged(shown in the unit test).
+func LinkSetBondSlaveActive(link Link, master *Bond) error {
+ err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
+ if err != nil {
+ return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
+ }
+ return nil
+}
+
+// LinkSetBondSlave add slave to bond link via ioctl interface.
+func LinkSetBondSlave(link Link, master *Bond) error {
+ err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
+ if err != nil {
+ return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
+ }
+ return nil
+}
+
+// LinkSetBondSlave removes specified slave from bond link via ioctl interface.
+func LinkDelBondSlave(link Link, master *Bond) error {
+ err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
+ if err != nil {
+ return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
}
return nil
}
diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
index eb3e1c16f7a..6989d1edc0b 100644
--- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
@@ -15,6 +15,38 @@ var L4ProtoMap = map[uint8]string{
17: "udp",
}
+// From https://git.netfilter.org/libnetfilter_conntrack/tree/include/libnetfilter_conntrack/libnetfilter_conntrack_tcp.h
+// enum tcp_state {
+// TCP_CONNTRACK_NONE,
+// TCP_CONNTRACK_SYN_SENT,
+// TCP_CONNTRACK_SYN_RECV,
+// TCP_CONNTRACK_ESTABLISHED,
+// TCP_CONNTRACK_FIN_WAIT,
+// TCP_CONNTRACK_CLOSE_WAIT,
+// TCP_CONNTRACK_LAST_ACK,
+// TCP_CONNTRACK_TIME_WAIT,
+// TCP_CONNTRACK_CLOSE,
+// TCP_CONNTRACK_LISTEN, /* obsolete */
+// #define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN
+// TCP_CONNTRACK_MAX,
+// TCP_CONNTRACK_IGNORE
+// };
+const (
+ TCP_CONNTRACK_NONE = 0
+ TCP_CONNTRACK_SYN_SENT = 1
+ TCP_CONNTRACK_SYN_RECV = 2
+ TCP_CONNTRACK_ESTABLISHED = 3
+ TCP_CONNTRACK_FIN_WAIT = 4
+ TCP_CONNTRACK_CLOSE_WAIT = 5
+ TCP_CONNTRACK_LAST_ACK = 6
+ TCP_CONNTRACK_TIME_WAIT = 7
+ TCP_CONNTRACK_CLOSE = 8
+ TCP_CONNTRACK_LISTEN = 9
+ TCP_CONNTRACK_SYN_SENT2 = 9
+ TCP_CONNTRACK_MAX = 10
+ TCP_CONNTRACK_IGNORE = 11
+)
+
// All the following constants are coming from:
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -31,6 +63,7 @@ var L4ProtoMap = map[uint8]string{
// IPCTNL_MSG_MAX
// };
const (
+ IPCTNL_MSG_CT_NEW = 0
IPCTNL_MSG_CT_GET = 1
IPCTNL_MSG_CT_DELETE = 2
)
@@ -91,6 +124,7 @@ const (
CTA_ZONE = 18
CTA_TIMESTAMP = 20
CTA_LABELS = 22
+ CTA_LABELS_MASK = 23
)
// enum ctattr_tuple {
@@ -151,7 +185,10 @@ const (
// };
// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
const (
+ CTA_PROTOINFO_UNSPEC = 0
CTA_PROTOINFO_TCP = 1
+ CTA_PROTOINFO_DCCP = 2
+ CTA_PROTOINFO_SCTP = 3
)
// enum ctattr_protoinfo_tcp {
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index 9492c5c73c3..0b5be470cb0 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -144,7 +144,9 @@ const (
IFLA_MACVLAN_MACADDR
IFLA_MACVLAN_MACADDR_DATA
IFLA_MACVLAN_MACADDR_COUNT
- IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
+ IFLA_MACVLAN_BC_QUEUE_LEN
+ IFLA_MACVLAN_BC_QUEUE_LEN_USED
+ IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED
)
const (
@@ -321,7 +323,7 @@ const (
const (
SizeofVfMac = 0x24
SizeofVfVlan = 0x0c
- SizeofVfVlanInfo = 0x0e
+ SizeofVfVlanInfo = 0x10
SizeofVfTxRate = 0x08
SizeofVfRate = 0x0c
SizeofVfSpoofchk = 0x08
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index c0cef5a1947..f4efae39c83 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -488,10 +488,30 @@ func (req *NetlinkRequest) AddRawData(data []byte) {
req.RawData = append(req.RawData, data...)
}
-// Execute the request against a the given sockType.
+// Execute the request against the given sockType.
// Returns a list of netlink messages in serialized format, optionally filtered
// by resType.
func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
+ var res [][]byte
+ err := req.ExecuteIter(sockType, resType, func(msg []byte) bool {
+ res = append(res, msg)
+ return true
+ })
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+}
+
+// ExecuteIter executes the request against the given sockType.
+// Calls the provided callback func once for each netlink message.
+// If the callback returns false, it is not called again, but
+// the remaining messages are consumed/discarded.
+//
+// Thread safety: ExecuteIter holds a lock on the socket until
+// it finishes iteration so the callback must not call back into
+// the netlink API.
+func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg []byte) bool) error {
var (
s *NetlinkSocket
err error
@@ -508,18 +528,18 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
if s == nil {
s, err = getNetlinkSocket(sockType)
if err != nil {
- return nil, err
+ return err
}
if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
- return nil, err
+ return err
}
if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
- return nil, err
+ return err
}
if EnableErrorMessageReporting {
if err := s.SetExtAck(true); err != nil {
- return nil, err
+ return err
}
}
@@ -530,38 +550,36 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
}
if err := s.Send(req); err != nil {
- return nil, err
+ return err
}
pid, err := s.GetPid()
if err != nil {
- return nil, err
+ return err
}
- var res [][]byte
-
done:
for {
msgs, from, err := s.Receive()
if err != nil {
- return nil, err
+ return err
}
if from.Pid != PidKernel {
- return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
+ return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
}
for _, m := range msgs {
if m.Header.Seq != req.Seq {
if sharedSocket {
continue
}
- return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
+ return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
}
if m.Header.Pid != pid {
continue
}
if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 {
- return nil, syscall.Errno(unix.EINTR)
+ return syscall.Errno(unix.EINTR)
}
if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR {
@@ -600,18 +618,26 @@ done:
}
}
- return nil, err
+ return err
}
if resType != 0 && m.Header.Type != resType {
continue
}
- res = append(res, m.Data)
+ if cont := f(m.Data); !cont {
+ // Drain the rest of the messages from the kernel but don't
+ // pass them to the iterator func.
+ f = dummyMsgIterFunc
+ }
if m.Header.Flags&unix.NLM_F_MULTI == 0 {
break done
}
}
}
- return res, nil
+ return nil
+}
+
+func dummyMsgIterFunc(msg []byte) bool {
+ return true
}
// Create a new netlink request from proto and flags
@@ -883,6 +909,12 @@ func Uint16Attr(v uint16) []byte {
return bytes
}
+func BEUint16Attr(v uint16) []byte {
+ bytes := make([]byte, 2)
+ binary.BigEndian.PutUint16(bytes, v)
+ return bytes
+}
+
func Uint32Attr(v uint32) []byte {
native := NativeEndian()
bytes := make([]byte, 4)
@@ -890,6 +922,12 @@ func Uint32Attr(v uint32) []byte {
return bytes
}
+func BEUint32Attr(v uint32) []byte {
+ bytes := make([]byte, 4)
+ binary.BigEndian.PutUint32(bytes, v)
+ return bytes
+}
+
func Uint64Attr(v uint64) []byte {
native := NativeEndian()
bytes := make([]byte, 8)
@@ -897,6 +935,12 @@ func Uint64Attr(v uint64) []byte {
return bytes
}
+func BEUint64Attr(v uint64) []byte {
+ bytes := make([]byte, 8)
+ binary.BigEndian.PutUint64(bytes, v)
+ return bytes
+}
+
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
var attrs []syscall.NetlinkRouteAttr
for len(b) >= unix.SizeofRtAttr {
diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
index 1500177267a..8172b8471f2 100644
--- a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
@@ -12,6 +12,7 @@ const (
SEG6_LOCAL_NH6
SEG6_LOCAL_IIF
SEG6_LOCAL_OIF
+ SEG6_LOCAL_BPF
__SEG6_LOCAL_MAX
)
const (
@@ -34,6 +35,7 @@ const (
SEG6_LOCAL_ACTION_END_S // 12
SEG6_LOCAL_ACTION_END_AS // 13
SEG6_LOCAL_ACTION_END_AM // 14
+ SEG6_LOCAL_ACTION_END_BPF // 15
__SEG6_LOCAL_ACTION_MAX
)
const (
@@ -71,6 +73,8 @@ func SEG6LocalActionString(action int) string {
return "End.AS"
case SEG6_LOCAL_ACTION_END_AM:
return "End.AM"
+ case SEG6_LOCAL_ACTION_END_BPF:
+ return "End.BPF"
}
return "unknown"
}
diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go
index 6f5d6df43b9..067743d390d 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc.go
@@ -123,6 +123,7 @@ type Htb struct {
Defcls uint32
Debug uint32
DirectPkts uint32
+ DirectQlen *uint32
}
func NewHtb(attrs QdiscAttrs) *Htb {
@@ -133,6 +134,7 @@ func NewHtb(attrs QdiscAttrs) *Htb {
Rate2Quantum: 10,
Debug: 0,
DirectPkts: 0,
+ DirectQlen: nil,
}
}
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index 3c3780d3d45..e732ae3bd64 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"strconv"
"strings"
+ "sync"
"syscall"
"github.com/vishvananda/netlink/nl"
@@ -200,7 +201,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
opt.Debug = qdisc.Debug
opt.DirectPkts = qdisc.DirectPkts
options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize())
- // options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
+ if qdisc.DirectQlen != nil {
+ options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, nl.Uint32Attr(*qdisc.DirectQlen))
+ }
case *Hfsc:
opt := nl.TcHfscOpt{}
opt.Defcls = qdisc.Defcls
@@ -525,8 +528,8 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
htb.Debug = opt.Debug
htb.DirectPkts = opt.DirectPkts
case nl.TCA_HTB_DIRECT_QLEN:
- // TODO
- //htb.DirectQlen = native.uint32(datum.Value)
+ directQlen := native.Uint32(datum.Value)
+ htb.DirectQlen = &directQlen
}
}
return nil
@@ -688,6 +691,9 @@ var (
tickInUsec float64
clockFactor float64
hz float64
+
+ // Without this, the go race detector may report races.
+ initClockMutex sync.Mutex
)
func initClock() {
@@ -722,6 +728,8 @@ func initClock() {
}
func TickInUsec() float64 {
+ initClockMutex.Lock()
+ defer initClockMutex.Unlock()
if tickInUsec == 0.0 {
initClock()
}
@@ -729,6 +737,8 @@ func TickInUsec() float64 {
}
func ClockFactor() float64 {
+ initClockMutex.Lock()
+ defer initClockMutex.Unlock()
if clockFactor == 0.0 {
initClock()
}
@@ -736,6 +746,8 @@ func ClockFactor() float64 {
}
func Hz() float64 {
+ initClockMutex.Lock()
+ defer initClockMutex.Unlock()
if hz == 0.0 {
initClock()
}
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 929738e1171..0cd4f8363a7 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -273,6 +273,16 @@ type SEG6LocalEncap struct {
In6Addr net.IP
Iif int
Oif int
+ bpf bpfObj
+}
+
+func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error {
+ if progFd <= 0 {
+ return fmt.Errorf("seg6local bpf SetProg: invalid fd")
+ }
+ e.bpf.progFd = progFd
+ e.bpf.progName = progName
+ return nil
}
func (e *SEG6LocalEncap) Type() int {
@@ -306,6 +316,22 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
case nl.SEG6_LOCAL_OIF:
e.Oif = int(native.Uint32(attr.Value[0:4]))
e.Flags[nl.SEG6_LOCAL_OIF] = true
+ case nl.SEG6_LOCAL_BPF:
+ var bpfAttrs []syscall.NetlinkRouteAttr
+ bpfAttrs, err = nl.ParseRouteAttr(attr.Value)
+ bpfobj := bpfObj{}
+ for _, bpfAttr := range bpfAttrs {
+ switch bpfAttr.Attr.Type {
+ case nl.LWT_BPF_PROG_FD:
+ bpfobj.progFd = int(native.Uint32(bpfAttr.Value))
+ case nl.LWT_BPF_PROG_NAME:
+ bpfobj.progName = string(bpfAttr.Value)
+ default:
+ err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr)
+ }
+ }
+ e.bpf = bpfobj
+ e.Flags[nl.SEG6_LOCAL_BPF] = true
}
}
return err
@@ -367,6 +393,16 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
native.PutUint32(attr[4:], uint32(e.Oif))
res = append(res, attr...)
}
+ if e.Flags[nl.SEG6_LOCAL_BPF] {
+ attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{})
+ if e.bpf.progFd != 0 {
+ attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd)))
+ }
+ if e.bpf.progName != "" {
+ attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName))
+ }
+ res = append(res, attr.Serialize()...)
+ }
return res, err
}
func (e *SEG6LocalEncap) String() string {
@@ -400,12 +436,15 @@ func (e *SEG6LocalEncap) String() string {
}
if e.Flags[nl.SEG6_LOCAL_SRH] {
segs := make([]string, 0, len(e.Segments))
- //append segment backwards (from n to 0) since seg#0 is the last segment.
+ // append segment backwards (from n to 0) since seg#0 is the last segment.
for i := len(e.Segments); i > 0; i-- {
segs = append(segs, e.Segments[i-1].String())
}
strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
}
+ if e.Flags[nl.SEG6_LOCAL_BPF] {
+ strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd))
+ }
return strings.Join(strs, " ")
}
func (e *SEG6LocalEncap) Equal(x Encap) bool {
@@ -437,7 +476,7 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
return false
}
- if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif {
+ if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
return false
}
return true
@@ -835,8 +874,22 @@ func (h *Handle) RouteDel(route *Route) error {
}
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) {
+ if err := h.prepareRouteReq(route, req, msg); err != nil {
+ return nil, err
+ }
+ return req.Execute(unix.NETLINK_ROUTE, 0)
+}
+
+func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error {
+ if err := h.prepareRouteReq(route, req, msg); err != nil {
+ return err
+ }
+ return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f)
+}
+
+func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
- return nil, fmt.Errorf("Either Dst.IP, Src.IP or Gw must be set")
+ return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set")
}
family := -1
@@ -863,11 +916,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if route.NewDst != nil {
if family != -1 && family != route.NewDst.Family() {
- return nil, fmt.Errorf("new destination and destination are not the same address family")
+ return fmt.Errorf("new destination and destination are not the same address family")
}
buf, err := route.NewDst.Encode()
if err != nil {
- return nil, err
+ return err
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf))
}
@@ -878,7 +931,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := route.Encap.Encode()
if err != nil {
- return nil, err
+ return err
}
switch route.Encap.Type() {
case nl.LWTUNNEL_ENCAP_BPF:
@@ -892,7 +945,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if route.Src != nil {
srcFamily := nl.GetIPFamily(route.Src)
if family != -1 && family != srcFamily {
- return nil, fmt.Errorf("source and destination ip are not the same IP family")
+ return fmt.Errorf("source and destination ip are not the same IP family")
}
family = srcFamily
var srcData []byte
@@ -908,7 +961,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if route.Gw != nil {
gwFamily := nl.GetIPFamily(route.Gw)
if family != -1 && family != gwFamily {
- return nil, fmt.Errorf("gateway, source, and destination ip are not the same IP family")
+ return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
}
family = gwFamily
var gwData []byte
@@ -923,7 +976,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if route.Via != nil {
buf, err := route.Via.Encode()
if err != nil {
- return nil, fmt.Errorf("failed to encode RTA_VIA: %v", err)
+ return fmt.Errorf("failed to encode RTA_VIA: %v", err)
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf))
}
@@ -942,7 +995,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if nh.Gw != nil {
gwFamily := nl.GetIPFamily(nh.Gw)
if family != -1 && family != gwFamily {
- return nil, fmt.Errorf("gateway, source, and destination ip are not the same IP family")
+ return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
}
if gwFamily == FAMILY_V4 {
children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4())))
@@ -952,11 +1005,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
}
if nh.NewDst != nil {
if family != -1 && family != nh.NewDst.Family() {
- return nil, fmt.Errorf("new destination and destination are not the same address family")
+ return fmt.Errorf("new destination and destination are not the same address family")
}
buf, err := nh.NewDst.Encode()
if err != nil {
- return nil, err
+ return err
}
children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf))
}
@@ -966,14 +1019,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := nh.Encap.Encode()
if err != nil {
- return nil, err
+ return err
}
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
}
if nh.Via != nil {
buf, err := nh.Via.Encode()
if err != nil {
- return nil, err
+ return err
}
children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf))
}
@@ -1104,8 +1157,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
native.PutUint32(b, uint32(route.LinkIndex))
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
}
-
- return req.Execute(unix.NETLINK_ROUTE, 0)
+ return nil
}
// RouteList gets a list of routes in the system.
@@ -1137,73 +1189,94 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
// All rules must be defined in RouteFilter struct
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
- req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
- rtmsg := &nl.RtMsg{}
- rtmsg.Family = uint8(family)
- msgs, err := h.routeHandle(filter, req, rtmsg)
+ var res []Route
+ err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) {
+ res = append(res, route)
+ return true
+ })
if err != nil {
return nil, err
}
+ return res, nil
+}
- var res []Route
- for _, m := range msgs {
+// RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues
+// until all routes are loaded or the func returns false.
+func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
+ return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f)
+}
+
+func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
+ req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
+ rtmsg := &nl.RtMsg{}
+ rtmsg.Family = uint8(family)
+
+ var parseErr error
+ err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool {
msg := nl.DeserializeRtMsg(m)
if family != FAMILY_ALL && msg.Family != uint8(family) {
// Ignore routes not matching requested family
- continue
+ return true
}
if msg.Flags&unix.RTM_F_CLONED != 0 {
// Ignore cloned routes
- continue
+ return true
}
if msg.Table != unix.RT_TABLE_MAIN {
if filter == nil || filterMask&RT_FILTER_TABLE == 0 {
// Ignore non-main tables
- continue
+ return true
}
}
route, err := deserializeRoute(m)
if err != nil {
- return nil, err
+ parseErr = err
+ return false
}
if filter != nil {
switch {
case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
- continue
+ return true
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
- continue
+ return true
case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
- continue
+ return true
case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
- continue
+ return true
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
- continue
+ return true
case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
- continue
+ return true
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
- continue
+ return true
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
- continue
+ return true
case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
- continue
+ return true
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
- continue
+ return true
case filterMask&RT_FILTER_DST != 0:
if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
if filter.Dst == nil {
filter.Dst = genZeroIPNet(family)
}
if !ipNetEqual(route.Dst, filter.Dst) {
- continue
+ return true
}
}
case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
- continue
+ return true
}
}
- res = append(res, route)
+ return f(route)
+ })
+ if err != nil {
+ return err
}
- return res, nil
+ if parseErr != nil {
+ return parseErr
+ }
+ return nil
}
// deserializeRoute decodes a binary netlink message into a Route struct
@@ -1448,7 +1521,7 @@ type RouteGetOptions struct {
VrfName string
SrcAddr net.IP
UID *uint32
- Mark int
+ Mark uint32
FIBMatch bool
}
@@ -1557,7 +1630,7 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
if options.Mark > 0 {
b := make([]byte, 4)
- native.PutUint32(b, uint32(options.Mark))
+ native.PutUint32(b, options.Mark)
req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
}
@@ -1723,7 +1796,7 @@ func (p RouteProtocol) String() string {
return "gated"
case unix.RTPROT_ISIS:
return "isis"
- //case unix.RTPROT_KEEPALIVED:
+ // case unix.RTPROT_KEEPALIVED:
// return "keepalived"
case unix.RTPROT_KERNEL:
return "kernel"
diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go
index 9a6b57dac47..cc7394588ec 100644
--- a/vendor/github.com/vishvananda/netlink/rule.go
+++ b/vendor/github.com/vishvananda/netlink/rule.go
@@ -10,8 +10,8 @@ type Rule struct {
Priority int
Family int
Table int
- Mark int
- Mask int
+ Mark uint32
+ Mask *uint32
Tos uint
TunID uint
Goto int
@@ -51,8 +51,8 @@ func NewRule() *Rule {
SuppressIfgroup: -1,
SuppressPrefixlen: -1,
Priority: -1,
- Mark: -1,
- Mask: -1,
+ Mark: 0,
+ Mask: nil,
Goto: -1,
Flow: -1,
}
diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go
index e91989251b6..18c03a3ebdf 100644
--- a/vendor/github.com/vishvananda/netlink/rule_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rule_linux.go
@@ -102,14 +102,14 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
native.PutUint32(b, uint32(rule.Priority))
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
}
- if rule.Mark >= 0 {
+ if rule.Mark != 0 || rule.Mask != nil {
b := make([]byte, 4)
- native.PutUint32(b, uint32(rule.Mark))
+ native.PutUint32(b, rule.Mark)
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
}
- if rule.Mask >= 0 {
+ if rule.Mask != nil {
b := make([]byte, 4)
- native.PutUint32(b, uint32(rule.Mask))
+ native.PutUint32(b, *rule.Mask)
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
}
if rule.Flow >= 0 {
@@ -242,9 +242,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
}
case nl.FRA_FWMARK:
- rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
+ rule.Mark = native.Uint32(attrs[j].Value[0:4])
case nl.FRA_FWMASK:
- rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
+ mask := native.Uint32(attrs[j].Value[0:4])
+ rule.Mask = &mask
case nl.FRA_TUN_ID:
rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
case nl.FRA_IIFNAME:
@@ -297,7 +298,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
continue
case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark:
continue
- case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask:
+ case filterMask&RT_FILTER_MASK != 0 && !ptrEqual(rule.Mask, filter.Mask):
continue
}
}
@@ -321,3 +322,13 @@ func (pr *RuleUIDRange) toRtAttrData() []byte {
native.PutUint32(b[1], pr.End)
return bytes.Join(b, []byte{})
}
+
+func ptrEqual(a, b *uint32) bool {
+ if a == b {
+ return true
+ }
+ if (a == nil) || (b == nil) {
+ return false
+ }
+ return *a == *b
+}
diff --git a/vendor/github.com/vishvananda/netlink/socket.go b/vendor/github.com/vishvananda/netlink/socket.go
index ebcf8423bf0..e65efb130f5 100644
--- a/vendor/github.com/vishvananda/netlink/socket.go
+++ b/vendor/github.com/vishvananda/netlink/socket.go
@@ -35,3 +35,70 @@ type UnixSocket struct {
INode uint32
Cookie [2]uint32
}
+
+// XDPSocket represents an XDP socket (and the common diagnosis part in
+// particular). Please note that in contrast to [UnixSocket] the XDPSocket type
+// does not feature “State” information.
+type XDPSocket struct {
+ // xdp_diag_msg
+ // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
+ Family uint8
+ Type uint8
+ pad uint16
+ Ino uint32
+ Cookie [2]uint32
+}
+
+type XDPInfo struct {
+ // XDP_DIAG_INFO/xdp_diag_info
+ // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L51
+ Ifindex uint32
+ QueueID uint32
+
+ // XDP_DIAG_UID
+ UID uint32
+
+ // XDP_RX_RING
+ // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L56
+ RxRingEntries uint32
+ TxRingEntries uint32
+ UmemFillRingEntries uint32
+ UmemCompletionRingEntries uint32
+
+ // XDR_DIAG_UMEM
+ Umem *XDPDiagUmem
+
+ // XDR_DIAG_STATS
+ Stats *XDPDiagStats
+}
+
+const (
+ XDP_DU_F_ZEROCOPY = 1 << iota
+)
+
+// XDPDiagUmem describes the umem attached to an XDP socket.
+//
+// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L62
+type XDPDiagUmem struct {
+ Size uint64
+ ID uint32
+ NumPages uint32
+ ChunkSize uint32
+ Headroom uint32
+ Ifindex uint32
+ QueueID uint32
+ Flags uint32
+ Refs uint32
+}
+
+// XDPDiagStats contains ring statistics for an XDP socket.
+//
+// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L74
+type XDPDiagStats struct {
+ RxDropped uint64
+ RxInvalid uint64
+ RxFull uint64
+ FillRingEmpty uint64
+ TxInvalid uint64
+ TxRingEmpty uint64
+}
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index e4b6fa73eaa..4eb4aeafbdf 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -157,7 +157,7 @@ func (u *UnixSocket) deserialize(b []byte) error {
}
// SocketGet returns the Socket identified by its local and remote addresses.
-func SocketGet(local, remote net.Addr) (*Socket, error) {
+func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) {
var protocol uint8
var localIP, remoteIP net.IP
var localPort, remotePort uint16
@@ -199,12 +199,7 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
return nil, ErrNotImplemented
}
- s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
- if err != nil {
- return nil, err
- }
- defer s.Close()
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&socketRequest{
Family: family,
Protocol: protocol,
@@ -218,32 +213,31 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
},
})
- if err := s.Send(req); err != nil {
- return nil, err
- }
-
- msgs, from, err := s.Receive()
+ msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY)
if err != nil {
return nil, err
}
- if from.Pid != nl.PidKernel {
- return nil, fmt.Errorf("wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
- }
if len(msgs) == 0 {
return nil, errors.New("no message nor error from netlink")
}
if len(msgs) > 2 {
return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs))
}
+
sock := &Socket{}
- if err := sock.deserialize(msgs[0].Data); err != nil {
+ if err := sock.deserialize(msgs[0]); err != nil {
return nil, err
}
return sock, nil
}
+// SocketGet returns the Socket identified by its local and remote addresses.
+func SocketGet(local, remote net.Addr) (*Socket, error) {
+ return pkgHandle.SocketGet(local, remote)
+}
+
// SocketDestroy kills the Socket identified by its local and remote addresses.
-func SocketDestroy(local, remote net.Addr) error {
+func (h *Handle) SocketDestroy(local, remote net.Addr) error {
localTCP, ok := local.(*net.TCPAddr)
if !ok {
return ErrNotImplemented
@@ -266,7 +260,7 @@ func SocketDestroy(local, remote net.Addr) error {
return err
}
defer s.Close()
- req := nl.NewNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK)
+ req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK)
req.AddData(&socketRequest{
Family: unix.AF_INET,
Protocol: unix.IPPROTO_TCP,
@@ -278,13 +272,20 @@ func SocketDestroy(local, remote net.Addr) error {
Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
},
})
- return s.Send(req)
+
+ _, err = req.Execute(unix.NETLINK_INET_DIAG, 0)
+ return err
+}
+
+// SocketDestroy kills the Socket identified by its local and remote addresses.
+func SocketDestroy(local, remote net.Addr) error {
+ return pkgHandle.SocketDestroy(local, remote)
}
// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
-func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
+func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
// Construct the request
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_TCP,
@@ -294,34 +295,41 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
// Do the query and parse the result
var result []*InetDiagTCPInfoResp
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
- attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
- if err != nil {
- return err
+ var attrs []syscall.NetlinkRouteAttr
+ if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
+ return false
}
- res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
- if err != nil {
- return err
+ var res *InetDiagTCPInfoResp
+ if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil {
+ return false
}
result = append(result, res)
- return nil
+ return true
})
+
if err != nil {
return nil, err
}
return result, nil
}
+// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
+func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
+ return pkgHandle.SocketDiagTCPInfo(family)
+}
+
// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
-func SocketDiagTCP(family uint8) ([]*Socket, error) {
+func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) {
// Construct the request
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_TCP,
@@ -331,13 +339,14 @@ func SocketDiagTCP(family uint8) ([]*Socket, error) {
// Do the query and parse the result
var result []*Socket
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
result = append(result, sockInfo)
- return nil
+ return true
})
if err != nil {
return nil, err
@@ -345,15 +354,20 @@ func SocketDiagTCP(family uint8) ([]*Socket, error) {
return result, nil
}
+// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
+func SocketDiagTCP(family uint8) ([]*Socket, error) {
+ return pkgHandle.SocketDiagTCP(family)
+}
+
// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
-func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
+func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
// Construct the request
var extensions uint8
extensions = 1 << (INET_DIAG_VEGASINFO - 1)
extensions |= 1 << (INET_DIAG_INFO - 1)
extensions |= 1 << (INET_DIAG_MEMINFO - 1)
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_UDP,
@@ -363,23 +377,25 @@ func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
// Do the query and parse the result
var result []*InetDiagUDPInfoResp
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
- attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
- if err != nil {
- return err
+
+ var attrs []syscall.NetlinkRouteAttr
+ if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
+ return false
}
- res, err := attrsToInetDiagUDPInfoResp(attrs, sockInfo)
- if err != nil {
- return err
+ var res *InetDiagUDPInfoResp
+ if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil {
+ return false
}
result = append(result, res)
- return nil
+ return true
})
if err != nil {
return nil, err
@@ -387,10 +403,15 @@ func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
return result, nil
}
+// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
+func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
+ return pkgHandle.SocketDiagUDPInfo(family)
+}
+
// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
-func SocketDiagUDP(family uint8) ([]*Socket, error) {
+func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) {
// Construct the request
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_UDP,
@@ -400,13 +421,14 @@ func SocketDiagUDP(family uint8) ([]*Socket, error) {
// Do the query and parse the result
var result []*Socket
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
result = append(result, sockInfo)
- return nil
+ return true
})
if err != nil {
return nil, err
@@ -414,14 +436,19 @@ func SocketDiagUDP(family uint8) ([]*Socket, error) {
return result, nil
}
+// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
+func SocketDiagUDP(family uint8) ([]*Socket, error) {
+ return pkgHandle.SocketDiagUDP(family)
+}
+
// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
-func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
+func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
// Construct the request
var extensions uint8
extensions = 1 << UNIX_DIAG_NAME
extensions |= 1 << UNIX_DIAG_PEER
extensions |= 1 << UNIX_DIAG_RQLEN
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&unixSocketRequest{
Family: unix.AF_UNIX,
States: ^uint32(0), // all states
@@ -429,28 +456,29 @@ func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
})
var result []*UnixDiagInfoResp
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &UnixSocket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
// Diagnosis also delivers sockets with AF_INET family, filter those
if sockInfo.Family != unix.AF_UNIX {
- return nil
+ return false
}
- attrs, err := nl.ParseRouteAttr(m.Data[sizeofUnixSocket:])
- if err != nil {
- return err
+ var attrs []syscall.NetlinkRouteAttr
+ if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
+ return false
}
- res, err := attrsToUnixDiagInfoResp(attrs, sockInfo)
- if err != nil {
- return err
+ var res *UnixDiagInfoResp
+ if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil {
+ return false
}
result = append(result, res)
- return nil
+ return true
})
if err != nil {
return nil, err
@@ -458,27 +486,33 @@ func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
return result, nil
}
+// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
+func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
+ return pkgHandle.UnixSocketDiagInfo()
+}
+
// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
-func UnixSocketDiag() ([]*UnixSocket, error) {
+func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) {
// Construct the request
- req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
req.AddData(&unixSocketRequest{
Family: unix.AF_UNIX,
States: ^uint32(0), // all states
})
var result []*UnixSocket
- err := socketDiagExecutor(req, func(m syscall.NetlinkMessage) error {
+ var err error
+ err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
sockInfo := &UnixSocket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return err
+ if err = sockInfo.deserialize(msg); err != nil {
+ return false
}
// Diagnosis also delivers sockets with AF_INET family, filter those
if sockInfo.Family == unix.AF_UNIX {
result = append(result, sockInfo)
}
- return nil
+ return true
})
if err != nil {
return nil, err
@@ -486,42 +520,9 @@ func UnixSocketDiag() ([]*UnixSocket, error) {
return result, nil
}
-// socketDiagExecutor requests diagnoses info from the NETLINK_INET_DIAG socket for the specified request.
-func socketDiagExecutor(req *nl.NetlinkRequest, receiver func(syscall.NetlinkMessage) error) error {
- s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
- if err != nil {
- return err
- }
- defer s.Close()
- s.Send(req)
-
-loop:
- for {
- msgs, from, err := s.Receive()
- if err != nil {
- return err
- }
- if from.Pid != nl.PidKernel {
- return fmt.Errorf("wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
- }
- if len(msgs) == 0 {
- return errors.New("no message nor error from netlink")
- }
-
- for _, m := range msgs {
- switch m.Header.Type {
- case unix.NLMSG_DONE:
- break loop
- case unix.NLMSG_ERROR:
- error := int32(native.Uint32(m.Data[0:4]))
- return syscall.Errno(-error)
- }
- if err := receiver(m); err != nil {
- return err
- }
- }
- }
- return nil
+// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
+func UnixSocketDiag() ([]*UnixSocket, error) {
+ return pkgHandle.UnixSocketDiag()
}
func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
diff --git a/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
new file mode 100644
index 00000000000..20c82f9c766
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
@@ -0,0 +1,195 @@
+package netlink
+
+import (
+ "errors"
+ "fmt"
+ "syscall"
+
+ "github.com/vishvananda/netlink/nl"
+ "golang.org/x/sys/unix"
+)
+
+const (
+ sizeofXDPSocketRequest = 1 + 1 + 2 + 4 + 4 + 2*4
+ sizeofXDPSocket = 0x10
+)
+
+// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L12
+type xdpSocketRequest struct {
+ Family uint8
+ Protocol uint8
+ pad uint16
+ Ino uint32
+ Show uint32
+ Cookie [2]uint32
+}
+
+func (r *xdpSocketRequest) Serialize() []byte {
+ b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)}
+ b.Write(r.Family)
+ b.Write(r.Protocol)
+ native.PutUint16(b.Next(2), r.pad)
+ native.PutUint32(b.Next(4), r.Ino)
+ native.PutUint32(b.Next(4), r.Show)
+ native.PutUint32(b.Next(4), r.Cookie[0])
+ native.PutUint32(b.Next(4), r.Cookie[1])
+ return b.Bytes
+}
+
+func (r *xdpSocketRequest) Len() int { return sizeofXDPSocketRequest }
+
+func (s *XDPSocket) deserialize(b []byte) error {
+ if len(b) < sizeofXDPSocket {
+ return fmt.Errorf("XDP socket data short read (%d); want %d", len(b), sizeofXDPSocket)
+ }
+ rb := readBuffer{Bytes: b}
+ s.Family = rb.Read()
+ s.Type = rb.Read()
+ s.pad = native.Uint16(rb.Next(2))
+ s.Ino = native.Uint32(rb.Next(4))
+ s.Cookie[0] = native.Uint32(rb.Next(4))
+ s.Cookie[1] = native.Uint32(rb.Next(4))
+ return nil
+}
+
+// XDPSocketGet returns the XDP socket identified by its inode number and/or
+// socket cookie. Specify the cookie as SOCK_ANY_COOKIE if
+func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) {
+ // We have a problem here: dumping AF_XDP sockets currently does not support
+ // filtering. We thus need to dump all XSKs and then only filter afterwards
+ // :(
+ xsks, err := SocketDiagXDP()
+ if err != nil {
+ return nil, err
+ }
+ checkCookie := cookie != SOCK_ANY_COOKIE && cookie != 0
+ crumblingCookie := [2]uint32{uint32(cookie), uint32(cookie >> 32)}
+ checkIno := ino != 0
+ var xskinfo *XDPDiagInfoResp
+ for _, xsk := range xsks {
+ if checkIno && xsk.XDPDiagMsg.Ino != ino {
+ continue
+ }
+ if checkCookie && xsk.XDPDiagMsg.Cookie != crumblingCookie {
+ continue
+ }
+ if xskinfo != nil {
+ return nil, errors.New("multiple matching XDP sockets")
+ }
+ xskinfo = xsk
+ }
+ if xskinfo == nil {
+ return nil, errors.New("no matching XDP socket")
+ }
+ return xskinfo, nil
+}
+
+// SocketDiagXDP requests XDP_DIAG_INFO for XDP family sockets.
+func SocketDiagXDP() ([]*XDPDiagInfoResp, error) {
+ var result []*XDPDiagInfoResp
+ err := socketDiagXDPExecutor(func(m syscall.NetlinkMessage) error {
+ sockInfo := &XDPSocket{}
+ if err := sockInfo.deserialize(m.Data); err != nil {
+ return err
+ }
+ attrs, err := nl.ParseRouteAttr(m.Data[sizeofXDPSocket:])
+ if err != nil {
+ return err
+ }
+
+ res, err := attrsToXDPDiagInfoResp(attrs, sockInfo)
+ if err != nil {
+ return err
+ }
+
+ result = append(result, res)
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// socketDiagXDPExecutor requests XDP_DIAG_INFO for XDP family sockets.
+func socketDiagXDPExecutor(receiver func(syscall.NetlinkMessage) error) error {
+ s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
+ if err != nil {
+ return err
+ }
+ defer s.Close()
+
+ req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
+ req.AddData(&xdpSocketRequest{
+ Family: unix.AF_XDP,
+ Show: XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM | XDP_SHOW_STATS,
+ })
+ if err := s.Send(req); err != nil {
+ return err
+ }
+
+loop:
+ for {
+ msgs, from, err := s.Receive()
+ if err != nil {
+ return err
+ }
+ if from.Pid != nl.PidKernel {
+ return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ }
+ if len(msgs) == 0 {
+ return errors.New("no message nor error from netlink")
+ }
+
+ for _, m := range msgs {
+ switch m.Header.Type {
+ case unix.NLMSG_DONE:
+ break loop
+ case unix.NLMSG_ERROR:
+ error := int32(native.Uint32(m.Data[0:4]))
+ return syscall.Errno(-error)
+ }
+ if err := receiver(m); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func attrsToXDPDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *XDPSocket) (*XDPDiagInfoResp, error) {
+ resp := &XDPDiagInfoResp{
+ XDPDiagMsg: sockInfo,
+ XDPInfo: &XDPInfo{},
+ }
+ for _, a := range attrs {
+ switch a.Attr.Type {
+ case XDP_DIAG_INFO:
+ resp.XDPInfo.Ifindex = native.Uint32(a.Value[0:4])
+ resp.XDPInfo.QueueID = native.Uint32(a.Value[4:8])
+ case XDP_DIAG_UID:
+ resp.XDPInfo.UID = native.Uint32(a.Value[0:4])
+ case XDP_DIAG_RX_RING:
+ resp.XDPInfo.RxRingEntries = native.Uint32(a.Value[0:4])
+ case XDP_DIAG_TX_RING:
+ resp.XDPInfo.TxRingEntries = native.Uint32(a.Value[0:4])
+ case XDP_DIAG_UMEM_FILL_RING:
+ resp.XDPInfo.UmemFillRingEntries = native.Uint32(a.Value[0:4])
+ case XDP_DIAG_UMEM_COMPLETION_RING:
+ resp.XDPInfo.UmemCompletionRingEntries = native.Uint32(a.Value[0:4])
+ case XDP_DIAG_UMEM:
+ umem := &XDPDiagUmem{}
+ if err := umem.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ resp.XDPInfo.Umem = umem
+ case XDP_DIAG_STATS:
+ stats := &XDPDiagStats{}
+ if err := stats.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ resp.XDPInfo.Stats = stats
+ }
+ }
+ return resp, nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/xdp_diag.go b/vendor/github.com/vishvananda/netlink/xdp_diag.go
new file mode 100644
index 00000000000..e88825bf55e
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/xdp_diag.go
@@ -0,0 +1,34 @@
+package netlink
+
+import "github.com/vishvananda/netlink/nl"
+
+const SOCK_ANY_COOKIE = uint64(nl.TCPDIAG_NOCOOKIE)<<32 + uint64(nl.TCPDIAG_NOCOOKIE)
+
+// XDP diagnosis show flag constants to request particular information elements.
+const (
+ XDP_SHOW_INFO = 1 << iota
+ XDP_SHOW_RING_CFG
+ XDP_SHOW_UMEM
+ XDP_SHOW_MEMINFO
+ XDP_SHOW_STATS
+)
+
+// XDP diag element constants
+const (
+ XDP_DIAG_NONE = iota
+ XDP_DIAG_INFO // when using XDP_SHOW_INFO
+ XDP_DIAG_UID // when using XDP_SHOW_INFO
+ XDP_DIAG_RX_RING // when using XDP_SHOW_RING_CFG
+ XDP_DIAG_TX_RING // when using XDP_SHOW_RING_CFG
+ XDP_DIAG_UMEM // when using XDP_SHOW_UMEM
+ XDP_DIAG_UMEM_FILL_RING // when using XDP_SHOW_UMEM
+ XDP_DIAG_UMEM_COMPLETION_RING // when using XDP_SHOW_UMEM
+ XDP_DIAG_MEMINFO // when using XDP_SHOW_MEMINFO
+ XDP_DIAG_STATS // when using XDP_SHOW_STATS
+)
+
+// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
+type XDPDiagInfoResp struct {
+ XDPDiagMsg *XDPSocket
+ XDPInfo *XDPInfo
+}
diff --git a/vendor/github.com/vishvananda/netlink/xdp_linux.go b/vendor/github.com/vishvananda/netlink/xdp_linux.go
new file mode 100644
index 00000000000..896a406deb4
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/xdp_linux.go
@@ -0,0 +1,46 @@
+package netlink
+
+import (
+ "bytes"
+ "fmt"
+)
+
+const (
+ xdrDiagUmemLen = 8 + 8*4
+ xdrDiagStatsLen = 6 * 8
+)
+
+func (x *XDPDiagUmem) deserialize(b []byte) error {
+ if len(b) < xdrDiagUmemLen {
+ return fmt.Errorf("XDP umem diagnosis data short read (%d); want %d", len(b), xdrDiagUmemLen)
+ }
+
+ rb := bytes.NewBuffer(b)
+ x.Size = native.Uint64(rb.Next(8))
+ x.ID = native.Uint32(rb.Next(4))
+ x.NumPages = native.Uint32(rb.Next(4))
+ x.ChunkSize = native.Uint32(rb.Next(4))
+ x.Headroom = native.Uint32(rb.Next(4))
+ x.Ifindex = native.Uint32(rb.Next(4))
+ x.QueueID = native.Uint32(rb.Next(4))
+ x.Flags = native.Uint32(rb.Next(4))
+ x.Refs = native.Uint32(rb.Next(4))
+
+ return nil
+}
+
+func (x *XDPDiagStats) deserialize(b []byte) error {
+ if len(b) < xdrDiagStatsLen {
+ return fmt.Errorf("XDP diagnosis statistics short read (%d); want %d", len(b), xdrDiagStatsLen)
+ }
+
+ rb := bytes.NewBuffer(b)
+ x.RxDropped = native.Uint64(rb.Next(8))
+ x.RxInvalid = native.Uint64(rb.Next(8))
+ x.RxFull = native.Uint64(rb.Next(8))
+ x.FillRingEmpty = native.Uint64(rb.Next(8))
+ x.TxInvalid = native.Uint64(rb.Next(8))
+ x.TxRingEmpty = native.Uint64(rb.Next(8))
+
+ return nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index bf539c19bed..c77e6a85ea2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -745,7 +745,7 @@ github.com/stretchr/testify/suite
# github.com/subosito/gotenv v1.6.0
## explicit; go 1.18
github.com/subosito/gotenv
-# github.com/tidwall/gjson v1.17.0
+# github.com/tidwall/gjson v1.17.3
## explicit; go 1.12
github.com/tidwall/gjson
# github.com/tidwall/match v1.1.1
@@ -760,7 +760,7 @@ github.com/tklauser/go-sysconf
# github.com/tklauser/numcpus v0.6.0
## explicit; go 1.13
github.com/tklauser/numcpus
-# github.com/vishvananda/netlink v1.2.1-beta.2.0.20240524165444-4d4ba1473f21
+# github.com/vishvananda/netlink v1.2.1
## explicit; go 1.12
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl