Browse code

vendor: github.com/vishvananda/netlink 655392bc778a

full diff: https://github.com/vishvananda/netlink/compare/084abd93d350...655392bc778acd41a35de75f804fe7088e922e2b

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/02/13 00:14:20
Showing 12 changed files
... ...
@@ -94,7 +94,7 @@ require (
94 94
 	github.com/spf13/pflag v1.0.6
95 95
 	github.com/tonistiigi/go-archvariant v1.0.0
96 96
 	github.com/vbatts/tar-split v0.11.6
97
-	github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350
97
+	github.com/vishvananda/netlink v1.3.1-0.20250209162617-655392bc778a
98 98
 	github.com/vishvananda/netns v0.0.5
99 99
 	go.etcd.io/bbolt v1.3.11
100 100
 	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0
... ...
@@ -550,8 +550,8 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
550 550
 github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
551 551
 github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs=
552 552
 github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI=
553
-github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350 h1:w5OI+kArIBVksl8UGn6ARQshtPCQvDsbuA9NQie3GIg=
554
-github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
553
+github.com/vishvananda/netlink v1.3.1-0.20250209162617-655392bc778a h1:P8YrhmisX/O76LxBpE0Bj9jk3WEzO/tYVv+HHRQsrQQ=
554
+github.com/vishvananda/netlink v1.3.1-0.20250209162617-655392bc778a/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
555 555
 github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
556 556
 github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
557 557
 github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
... ...
@@ -18,6 +18,7 @@ import (
18 18
 //
19 19
 // If `addr` is an IPv4 address and the broadcast address is not given, it
20 20
 // will be automatically computed based on the IP mask if /30 or larger.
21
+// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled.
21 22
 func AddrAdd(link Link, addr *Addr) error {
22 23
 	return pkgHandle.AddrAdd(link, addr)
23 24
 }
... ...
@@ -28,6 +29,7 @@ func AddrAdd(link Link, addr *Addr) error {
28 28
 //
29 29
 // If `addr` is an IPv4 address and the broadcast address is not given, it
30 30
 // will be automatically computed based on the IP mask if /30 or larger.
31
+// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled.
31 32
 func (h *Handle) AddrAdd(link Link, addr *Addr) error {
32 33
 	req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
33 34
 	return h.addrHandle(link, addr, req)
... ...
@@ -39,6 +41,7 @@ func (h *Handle) AddrAdd(link Link, addr *Addr) error {
39 39
 //
40 40
 // If `addr` is an IPv4 address and the broadcast address is not given, it
41 41
 // will be automatically computed based on the IP mask if /30 or larger.
42
+// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled.
42 43
 func AddrReplace(link Link, addr *Addr) error {
43 44
 	return pkgHandle.AddrReplace(link, addr)
44 45
 }
... ...
@@ -49,6 +52,7 @@ func AddrReplace(link Link, addr *Addr) error {
49 49
 //
50 50
 // If `addr` is an IPv4 address and the broadcast address is not given, it
51 51
 // will be automatically computed based on the IP mask if /30 or larger.
52
+// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled.
52 53
 func (h *Handle) AddrReplace(link Link, addr *Addr) error {
53 54
 	req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
54 55
 	return h.addrHandle(link, addr, req)
... ...
@@ -57,18 +61,13 @@ func (h *Handle) AddrReplace(link Link, addr *Addr) error {
57 57
 // AddrDel will delete an IP address from a link device.
58 58
 //
59 59
 // Equivalent to: `ip addr del $addr dev $link`
60
-//
61
-// If `addr` is an IPv4 address and the broadcast address is not given, it
62
-// will be automatically computed based on the IP mask if /30 or larger.
63 60
 func AddrDel(link Link, addr *Addr) error {
64 61
 	return pkgHandle.AddrDel(link, addr)
65 62
 }
66 63
 
67 64
 // AddrDel will delete an IP address from a link device.
68
-// Equivalent to: `ip addr del $addr dev $link`
69 65
 //
70
-// If `addr` is an IPv4 address and the broadcast address is not given, it
71
-// will be automatically computed based on the IP mask if /30 or larger.
66
+// Equivalent to: `ip addr del $addr dev $link`
72 67
 func (h *Handle) AddrDel(link Link, addr *Addr) error {
73 68
 	req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
74 69
 	return h.addrHandle(link, addr, req)
... ...
@@ -142,6 +141,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
142 142
 			addr.Broadcast = calcBroadcast
143 143
 		}
144 144
 
145
+		if net.IPv4zero.Equal(addr.Broadcast) {
146
+			addr.Broadcast = nil
147
+		}
148
+
145 149
 		if addr.Broadcast != nil {
146 150
 			req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
147 151
 		}
... ...
@@ -5,8 +5,8 @@ import (
5 5
 	"encoding/binary"
6 6
 	"errors"
7 7
 	"fmt"
8
+	"io/fs"
8 9
 	"net"
9
-	"strings"
10 10
 	"time"
11 11
 
12 12
 	"github.com/vishvananda/netlink/nl"
... ...
@@ -159,13 +159,19 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
159 159
 // ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
160 160
 // conntrack -D [table] parameters         Delete conntrack or expectation
161 161
 func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
162
+	var finalErr error
162 163
 	res, err := h.dumpConntrackTable(table, family)
163 164
 	if err != nil {
164
-		return 0, err
165
+		if !errors.Is(err, ErrDumpInterrupted) {
166
+			return 0, err
167
+		}
168
+		// This allows us to at least do a best effort to try to clean the
169
+		// entries matching the filter.
170
+		finalErr = err
165 171
 	}
166 172
 
173
+	var totalFilterErrors int
167 174
 	var matched uint
168
-	var errMsgs []string
169 175
 	for _, dataRaw := range res {
170 176
 		flow := parseRawData(dataRaw)
171 177
 		for _, filter := range filters {
... ...
@@ -173,19 +179,20 @@ func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFam
173 173
 				req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
174 174
 				// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
175 175
 				req2.AddRawData(dataRaw[4:])
176
-				if _, err = req2.Execute(unix.NETLINK_NETFILTER, 0); err == nil {
176
+				if _, err = req2.Execute(unix.NETLINK_NETFILTER, 0); err == nil || errors.Is(err, fs.ErrNotExist) {
177 177
 					matched++
178 178
 					// flow is already deleted, no need to match on other filters and continue to the next flow.
179 179
 					break
180
+				} else {
181
+					totalFilterErrors++
180 182
 				}
181
-				errMsgs = append(errMsgs, fmt.Sprintf("failed to delete conntrack flow '%s': %s", flow.String(), err.Error()))
182 183
 			}
183 184
 		}
184 185
 	}
185
-	if len(errMsgs) > 0 {
186
-		return matched, fmt.Errorf(strings.Join(errMsgs, "; "))
186
+	if totalFilterErrors > 0 {
187
+		finalErr = errors.Join(finalErr, fmt.Errorf("failed to delete %d conntrack flows with %d filters", totalFilterErrors, len(filters)))
187 188
 	}
188
-	return matched, nil
189
+	return matched, finalErr
189 190
 }
190 191
 
191 192
 func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily, operation, flags int) *nl.NetlinkRequest {
... ...
@@ -231,6 +231,35 @@ func NewCsumAction() *CsumAction {
231 231
 	}
232 232
 }
233 233
 
234
+type VlanAct int8
235
+
236
+type VlanAction struct {
237
+	ActionAttrs
238
+	Action VlanAct
239
+	VlanID uint16
240
+}
241
+
242
+const (
243
+	TCA_VLAN_ACT_POP  VlanAct = 1
244
+	TCA_VLAN_ACT_PUSH VlanAct = 2
245
+)
246
+
247
+func (action *VlanAction) Type() string {
248
+	return "vlan"
249
+}
250
+
251
+func (action *VlanAction) Attrs() *ActionAttrs {
252
+	return &action.ActionAttrs
253
+}
254
+
255
+func NewVlanAction() *VlanAction {
256
+	return &VlanAction{
257
+		ActionAttrs: ActionAttrs{
258
+			Action: TC_ACT_PIPE,
259
+		},
260
+	}
261
+}
262
+
234 263
 type MirredAct uint8
235 264
 
236 265
 func (a MirredAct) String() string {
... ...
@@ -65,6 +65,9 @@ type Flower struct {
65 65
 	EncSrcIPMask  net.IPMask
66 66
 	EncDestPort   uint16
67 67
 	EncKeyId      uint32
68
+	SrcMac        net.HardwareAddr
69
+	DestMac       net.HardwareAddr
70
+	VlanId        uint16
68 71
 	SkipHw        bool
69 72
 	SkipSw        bool
70 73
 	IPProto       *nl.IPProto
... ...
@@ -135,6 +138,15 @@ func (filter *Flower) encode(parent *nl.RtAttr) error {
135 135
 	if filter.EncKeyId != 0 {
136 136
 		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
137 137
 	}
138
+	if filter.SrcMac != nil {
139
+		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac)
140
+	}
141
+	if filter.DestMac != nil {
142
+		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac)
143
+	}
144
+	if filter.VlanId != 0 {
145
+		parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId))
146
+	}
138 147
 	if filter.IPProto != nil {
139 148
 		ipproto := *filter.IPProto
140 149
 		parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
... ...
@@ -201,6 +213,13 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
201 201
 			filter.EncDestPort = ntohs(datum.Value)
202 202
 		case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
203 203
 			filter.EncKeyId = ntohl(datum.Value)
204
+		case nl.TCA_FLOWER_KEY_ETH_SRC:
205
+			filter.SrcMac = datum.Value
206
+		case nl.TCA_FLOWER_KEY_ETH_DST:
207
+			filter.DestMac = datum.Value
208
+		case nl.TCA_FLOWER_KEY_VLAN_ID:
209
+			filter.VlanId = native.Uint16(datum.Value[0:2])
210
+			filter.EthType = unix.ETH_P_8021Q
204 211
 		case nl.TCA_FLOWER_KEY_IP_PROTO:
205 212
 			val := new(nl.IPProto)
206 213
 			*val = nl.IPProto(datum.Value[0])
... ...
@@ -622,6 +641,22 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
622 622
 			}
623 623
 			toTcGen(action.Attrs(), &mirred.TcGen)
624 624
 			aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
625
+		case *VlanAction:
626
+			table := attr.AddRtAttr(tabIndex, nil)
627
+			tabIndex++
628
+			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan"))
629
+			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
630
+			vlan := nl.TcVlan{
631
+				Action: int32(action.Action),
632
+			}
633
+			toTcGen(action.Attrs(), &vlan.TcGen)
634
+			aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize())
635
+			if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 {
636
+				return fmt.Errorf("vlan id is required for push action")
637
+			}
638
+			if action.VlanID != 0 {
639
+				aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID))
640
+			}
625 641
 		case *TunnelKeyAction:
626 642
 			table := attr.AddRtAttr(tabIndex, nil)
627 643
 			tabIndex++
... ...
@@ -792,6 +827,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
792 792
 					action = &CsumAction{}
793 793
 				case "gact":
794 794
 					action = &GenericAction{}
795
+				case "vlan":
796
+					action = &VlanAction{}
795 797
 				case "tunnel_key":
796 798
 					action = &TunnelKeyAction{}
797 799
 				case "skbedit":
... ...
@@ -822,7 +859,17 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
822 822
 							tcTs := nl.DeserializeTcf(adatum.Value)
823 823
 							actionTimestamp = toTimeStamp(tcTs)
824 824
 						}
825
-
825
+					case "vlan":
826
+						switch adatum.Attr.Type {
827
+						case nl.TCA_VLAN_PARMS:
828
+							vlan := *nl.DeserializeTcVlan(adatum.Value)
829
+							action.(*VlanAction).ActionAttrs = ActionAttrs{}
830
+							toAttrs(&vlan.TcGen, action.Attrs())
831
+							action.(*VlanAction).Action = VlanAct(vlan.Action)
832
+						case nl.TCA_VLAN_PUSH_VLAN_ID:
833
+							vlanId := native.Uint16(adatum.Value[0:2])
834
+							action.(*VlanAction).VlanID = vlanId
835
+						}
826 836
 					case "tunnel_key":
827 837
 						switch adatum.Attr.Type {
828 838
 						case nl.TCA_TUNNEL_KEY_PARMS:
... ...
@@ -56,6 +56,8 @@ type LinkAttrs struct {
56 56
 	Vfs            []VfInfo // virtual functions available on link
57 57
 	Group          uint32
58 58
 	PermHWAddr     net.HardwareAddr
59
+	ParentDev      string
60
+	ParentDevBus   string
59 61
 	Slave          LinkSlave
60 62
 }
61 63
 
... ...
@@ -377,6 +379,13 @@ const (
377 377
 	NETKIT_POLICY_BLACKHOLE NetkitPolicy = 2
378 378
 )
379 379
 
380
+type NetkitScrub int
381
+
382
+const (
383
+	NETKIT_SCRUB_NONE    NetkitScrub = 0
384
+	NETKIT_SCRUB_DEFAULT NetkitScrub = 1
385
+)
386
+
380 387
 func (n *Netkit) IsPrimary() bool {
381 388
 	return n.isPrimary
382 389
 }
... ...
@@ -391,6 +400,9 @@ type Netkit struct {
391 391
 	Mode          NetkitMode
392 392
 	Policy        NetkitPolicy
393 393
 	PeerPolicy    NetkitPolicy
394
+	Scrub         NetkitScrub
395
+	PeerScrub     NetkitScrub
396
+	supportsScrub bool
394 397
 	isPrimary     bool
395 398
 	peerLinkAttrs LinkAttrs
396 399
 }
... ...
@@ -403,6 +415,10 @@ func (n *Netkit) Type() string {
403 403
 	return "netkit"
404 404
 }
405 405
 
406
+func (n *Netkit) SupportsScrub() bool {
407
+	return n.supportsScrub
408
+}
409
+
406 410
 // Veth devices must specify PeerName on create
407 411
 type Veth struct {
408 412
 	LinkAttrs
... ...
@@ -761,19 +777,19 @@ const (
761 761
 )
762 762
 
763 763
 var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
764
-	BOND_XMIT_HASH_POLICY_LAYER2:   "layer2",
765
-	BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4",
766
-	BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
767
-	BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
768
-	BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
764
+	BOND_XMIT_HASH_POLICY_LAYER2:      "layer2",
765
+	BOND_XMIT_HASH_POLICY_LAYER3_4:    "layer3+4",
766
+	BOND_XMIT_HASH_POLICY_LAYER2_3:    "layer2+3",
767
+	BOND_XMIT_HASH_POLICY_ENCAP2_3:    "encap2+3",
768
+	BOND_XMIT_HASH_POLICY_ENCAP3_4:    "encap3+4",
769 769
 	BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac",
770 770
 }
771 771
 var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
772
-	"layer2":   BOND_XMIT_HASH_POLICY_LAYER2,
773
-	"layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4,
774
-	"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
775
-	"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
776
-	"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
772
+	"layer2":      BOND_XMIT_HASH_POLICY_LAYER2,
773
+	"layer3+4":    BOND_XMIT_HASH_POLICY_LAYER3_4,
774
+	"layer2+3":    BOND_XMIT_HASH_POLICY_LAYER2_3,
775
+	"encap2+3":    BOND_XMIT_HASH_POLICY_ENCAP2_3,
776
+	"encap3+4":    BOND_XMIT_HASH_POLICY_ENCAP3_4,
777 777
 	"vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC,
778 778
 }
779 779
 
... ...
@@ -2263,6 +2263,10 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
2263 2263
 					break
2264 2264
 				}
2265 2265
 			}
2266
+		case unix.IFLA_PARENT_DEV_NAME:
2267
+			base.ParentDev = string(attr.Value[:len(attr.Value)-1])
2268
+		case unix.IFLA_PARENT_DEV_BUS_NAME:
2269
+			base.ParentDevBus = string(attr.Value[:len(attr.Value)-1])
2266 2270
 		}
2267 2271
 	}
2268 2272
 
... ...
@@ -2676,6 +2680,8 @@ func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
2676 2676
 	data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
2677 2677
 	data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
2678 2678
 	data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
2679
+	data.AddRtAttr(nl.IFLA_NETKIT_SCRUB, nl.Uint32Attr(uint32(nk.Scrub)))
2680
+	data.AddRtAttr(nl.IFLA_NETKIT_PEER_SCRUB, nl.Uint32Attr(uint32(nk.PeerScrub)))
2679 2681
 
2680 2682
 	if (flag & unix.NLM_F_EXCL) == 0 {
2681 2683
 		// Modifying peer link attributes will not take effect
... ...
@@ -2736,6 +2742,12 @@ func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
2736 2736
 			netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
2737 2737
 		case nl.IFLA_NETKIT_PEER_POLICY:
2738 2738
 			netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
2739
+		case nl.IFLA_NETKIT_SCRUB:
2740
+			netkit.supportsScrub = true
2741
+			netkit.Scrub = NetkitScrub(native.Uint32(datum.Value[0:4]))
2742
+		case nl.IFLA_NETKIT_PEER_SCRUB:
2743
+			netkit.supportsScrub = true
2744
+			netkit.PeerScrub = NetkitScrub(native.Uint32(datum.Value[0:4]))
2739 2745
 		}
2740 2746
 	}
2741 2747
 }
... ...
@@ -3033,7 +3045,6 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
3033 3033
 	}
3034 3034
 }
3035 3035
 
3036
-// copied from pkg/net_linux.go
3037 3036
 func linkFlags(rawFlags uint32) net.Flags {
3038 3037
 	var f net.Flags
3039 3038
 	if rawFlags&unix.IFF_UP != 0 {
... ...
@@ -3051,6 +3062,9 @@ func linkFlags(rawFlags uint32) net.Flags {
3051 3051
 	if rawFlags&unix.IFF_MULTICAST != 0 {
3052 3052
 		f |= net.FlagMulticast
3053 3053
 	}
3054
+	if rawFlags&unix.IFF_RUNNING != 0 {
3055
+		f |= net.FlagRunning
3056
+	}
3054 3057
 	return f
3055 3058
 }
3056 3059
 
... ...
@@ -38,6 +38,8 @@ const (
38 38
 	IFLA_NETKIT_POLICY
39 39
 	IFLA_NETKIT_PEER_POLICY
40 40
 	IFLA_NETKIT_MODE
41
+	IFLA_NETKIT_SCRUB
42
+	IFLA_NETKIT_PEER_SCRUB
41 43
 	IFLA_NETKIT_MAX = IFLA_NETKIT_MODE
42 44
 )
43 45
 
... ...
@@ -17,7 +17,7 @@ func ParseAttributes(data []byte) <-chan Attribute {
17 17
 
18 18
 	go func() {
19 19
 		i := 0
20
-		for i+4 < len(data) {
20
+		for i+4 <= len(data) {
21 21
 			length := int(native.Uint16(data[i : i+2]))
22 22
 			attrType := native.Uint16(data[i+2 : i+4])
23 23
 
... ...
@@ -115,6 +115,7 @@ const (
115 115
 	SizeofTcConnmark     = SizeofTcGen + 0x04
116 116
 	SizeofTcCsum         = SizeofTcGen + 0x04
117 117
 	SizeofTcMirred       = SizeofTcGen + 0x08
118
+	SizeofTcVlan         = SizeofTcGen + 0x04
118 119
 	SizeofTcTunnelKey    = SizeofTcGen + 0x04
119 120
 	SizeofTcSkbEdit      = SizeofTcGen
120 121
 	SizeofTcPolice       = 2*SizeofTcRateSpec + 0x20
... ...
@@ -817,6 +818,41 @@ func (x *TcMirred) Serialize() []byte {
817 817
 }
818 818
 
819 819
 const (
820
+	TCA_VLAN_UNSPEC = iota
821
+	TCA_VLAN_TM
822
+	TCA_VLAN_PARMS
823
+	TCA_VLAN_PUSH_VLAN_ID
824
+	TCA_VLAN_PUSH_VLAN_PROTOCOL
825
+	TCA_VLAN_PAD
826
+	TCA_VLAN_PUSH_VLAN_PRIORITY
827
+	TCA_VLAN_PUSH_ETH_DST
828
+	TCA_VLAN_PUSH_ETH_SRC
829
+	TCA_VLAN_MAX
830
+)
831
+
832
+//struct tc_vlan {
833
+//	tc_gen;
834
+//	int v_action;
835
+//};
836
+
837
+type TcVlan struct {
838
+	TcGen
839
+	Action int32
840
+}
841
+
842
+func (msg *TcVlan) Len() int {
843
+	return SizeofTcVlan
844
+}
845
+
846
+func DeserializeTcVlan(b []byte) *TcVlan {
847
+	return (*TcVlan)(unsafe.Pointer(&b[0:SizeofTcVlan][0]))
848
+}
849
+
850
+func (x *TcVlan) Serialize() []byte {
851
+	return (*(*[SizeofTcVlan]byte)(unsafe.Pointer(x)))[:]
852
+}
853
+
854
+const (
820 855
 	TCA_TUNNEL_KEY_UNSPEC = iota
821 856
 	TCA_TUNNEL_KEY_TM
822 857
 	TCA_TUNNEL_KEY_PARMS
... ...
@@ -1239,8 +1275,8 @@ const (
1239 1239
 )
1240 1240
 
1241 1241
 // /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It
1242
-//  * means no specific header type - offset is relative to the network layer
1243
-//  */
1242
+//   - means no specific header type - offset is relative to the network layer
1243
+//     */
1244 1244
 type PeditHeaderType uint16
1245 1245
 
1246 1246
 const (
... ...
@@ -1156,7 +1156,7 @@ github.com/tonistiigi/vt100
1156 1156
 github.com/vbatts/tar-split/archive/tar
1157 1157
 github.com/vbatts/tar-split/tar/asm
1158 1158
 github.com/vbatts/tar-split/tar/storage
1159
-# github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350
1159
+# github.com/vishvananda/netlink v1.3.1-0.20250209162617-655392bc778a
1160 1160
 ## explicit; go 1.12
1161 1161
 github.com/vishvananda/netlink
1162 1162
 github.com/vishvananda/netlink/nl