github.com/vishvananda/netlink@v1.3.1/link_linux.go (about) 1 package netlink 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "net" 10 "os" 11 "strconv" 12 "strings" 13 "syscall" 14 "unsafe" 15 16 "github.com/vishvananda/netlink/nl" 17 "github.com/vishvananda/netns" 18 "golang.org/x/sys/unix" 19 ) 20 21 const ( 22 SizeofLinkStats32 = 0x5c 23 SizeofLinkStats64 = 0xb8 24 ) 25 26 const ( 27 TUNTAP_MODE_TUN TuntapMode = unix.IFF_TUN 28 TUNTAP_MODE_TAP TuntapMode = unix.IFF_TAP 29 TUNTAP_DEFAULTS TuntapFlag = unix.IFF_TUN_EXCL | unix.IFF_ONE_QUEUE 30 TUNTAP_VNET_HDR TuntapFlag = unix.IFF_VNET_HDR 31 TUNTAP_TUN_EXCL TuntapFlag = unix.IFF_TUN_EXCL 32 TUNTAP_NO_PI TuntapFlag = unix.IFF_NO_PI 33 TUNTAP_ONE_QUEUE TuntapFlag = unix.IFF_ONE_QUEUE 34 TUNTAP_MULTI_QUEUE TuntapFlag = unix.IFF_MULTI_QUEUE 35 TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI 36 ) 37 38 var StringToTuntapModeMap = map[string]TuntapMode{ 39 "tun": TUNTAP_MODE_TUN, 40 "tap": TUNTAP_MODE_TAP, 41 } 42 43 func (ttm TuntapMode) String() string { 44 switch ttm { 45 case TUNTAP_MODE_TUN: 46 return "tun" 47 case TUNTAP_MODE_TAP: 48 return "tap" 49 } 50 return "unknown" 51 } 52 53 const ( 54 VF_LINK_STATE_AUTO uint32 = 0 55 VF_LINK_STATE_ENABLE uint32 = 1 56 VF_LINK_STATE_DISABLE uint32 = 2 57 ) 58 59 var macvlanModes = [...]uint32{ 60 0, 61 nl.MACVLAN_MODE_PRIVATE, 62 nl.MACVLAN_MODE_VEPA, 63 nl.MACVLAN_MODE_BRIDGE, 64 nl.MACVLAN_MODE_PASSTHRU, 65 nl.MACVLAN_MODE_SOURCE, 66 } 67 68 func ensureIndex(link *LinkAttrs) { 69 if link != nil && link.Index == 0 { 70 newlink, _ := LinkByName(link.Name) 71 if newlink != nil { 72 link.Index = newlink.Attrs().Index 73 } 74 } 75 } 76 77 func (h *Handle) ensureIndex(link *LinkAttrs) { 78 if link != nil && link.Index == 0 { 79 newlink, _ := h.LinkByName(link.Name) 80 if newlink != nil { 81 link.Index = newlink.Attrs().Index 82 } 83 } 84 } 85 86 func (h *Handle) LinkSetARPOff(link Link) error { 87 base := link.Attrs() 88 h.ensureIndex(base) 89 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 90 91 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 92 msg.Change |= unix.IFF_NOARP 93 msg.Flags |= unix.IFF_NOARP 94 msg.Index = int32(base.Index) 95 req.AddData(msg) 96 97 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 98 return err 99 } 100 101 func LinkSetARPOff(link Link) error { 102 return pkgHandle.LinkSetARPOff(link) 103 } 104 105 func (h *Handle) LinkSetARPOn(link Link) error { 106 base := link.Attrs() 107 h.ensureIndex(base) 108 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 109 110 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 111 msg.Change |= unix.IFF_NOARP 112 msg.Flags &= ^uint32(unix.IFF_NOARP) 113 msg.Index = int32(base.Index) 114 req.AddData(msg) 115 116 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 117 return err 118 } 119 120 func LinkSetARPOn(link Link) error { 121 return pkgHandle.LinkSetARPOn(link) 122 } 123 124 func (h *Handle) SetPromiscOn(link Link) error { 125 base := link.Attrs() 126 h.ensureIndex(base) 127 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 128 129 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 130 msg.Change = unix.IFF_PROMISC 131 msg.Flags = unix.IFF_PROMISC 132 msg.Index = int32(base.Index) 133 req.AddData(msg) 134 135 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 136 return err 137 } 138 139 // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. 140 // Equivalent to: `ip link set $link allmulticast on` 141 func LinkSetAllmulticastOn(link Link) error { 142 return pkgHandle.LinkSetAllmulticastOn(link) 143 } 144 145 // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. 146 // Equivalent to: `ip link set $link allmulticast on` 147 func (h *Handle) LinkSetAllmulticastOn(link Link) error { 148 base := link.Attrs() 149 h.ensureIndex(base) 150 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 151 152 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 153 msg.Change = unix.IFF_ALLMULTI 154 msg.Flags = unix.IFF_ALLMULTI 155 msg.Index = int32(base.Index) 156 req.AddData(msg) 157 158 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 159 return err 160 } 161 162 // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. 163 // Equivalent to: `ip link set $link allmulticast off` 164 func LinkSetAllmulticastOff(link Link) error { 165 return pkgHandle.LinkSetAllmulticastOff(link) 166 } 167 168 // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. 169 // Equivalent to: `ip link set $link allmulticast off` 170 func (h *Handle) LinkSetAllmulticastOff(link Link) error { 171 base := link.Attrs() 172 h.ensureIndex(base) 173 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 174 175 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 176 msg.Change = unix.IFF_ALLMULTI 177 msg.Index = int32(base.Index) 178 req.AddData(msg) 179 180 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 181 return err 182 } 183 184 // LinkSetMulticastOn enables the reception of multicast packets for the link device. 185 // Equivalent to: `ip link set $link multicast on` 186 func LinkSetMulticastOn(link Link) error { 187 return pkgHandle.LinkSetMulticastOn(link) 188 } 189 190 // LinkSetMulticastOn enables the reception of multicast packets for the link device. 191 // Equivalent to: `ip link set $link multicast on` 192 func (h *Handle) LinkSetMulticastOn(link Link) error { 193 base := link.Attrs() 194 h.ensureIndex(base) 195 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 196 197 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 198 msg.Change = unix.IFF_MULTICAST 199 msg.Flags = unix.IFF_MULTICAST 200 msg.Index = int32(base.Index) 201 req.AddData(msg) 202 203 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 204 return err 205 } 206 207 // LinkSetAllmulticastOff disables the reception of multicast packets for the link device. 208 // Equivalent to: `ip link set $link multicast off` 209 func LinkSetMulticastOff(link Link) error { 210 return pkgHandle.LinkSetMulticastOff(link) 211 } 212 213 // LinkSetAllmulticastOff disables the reception of multicast packets for the link device. 214 // Equivalent to: `ip link set $link multicast off` 215 func (h *Handle) LinkSetMulticastOff(link Link) error { 216 base := link.Attrs() 217 h.ensureIndex(base) 218 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 219 220 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 221 msg.Change = unix.IFF_MULTICAST 222 msg.Index = int32(base.Index) 223 req.AddData(msg) 224 225 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 226 return err 227 } 228 229 func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { 230 return pkgHandle.MacvlanMACAddrAdd(link, addr) 231 } 232 233 func (h *Handle) MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { 234 return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_ADD) 235 } 236 237 func MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error { 238 return pkgHandle.MacvlanMACAddrDel(link, addr) 239 } 240 241 func (h *Handle) MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error { 242 return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_DEL) 243 } 244 245 func MacvlanMACAddrFlush(link Link) error { 246 return pkgHandle.MacvlanMACAddrFlush(link) 247 } 248 249 func (h *Handle) MacvlanMACAddrFlush(link Link) error { 250 return h.macvlanMACAddrChange(link, nil, nl.MACVLAN_MACADDR_FLUSH) 251 } 252 253 func MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error { 254 return pkgHandle.MacvlanMACAddrSet(link, addrs) 255 } 256 257 func (h *Handle) MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error { 258 return h.macvlanMACAddrChange(link, addrs, nl.MACVLAN_MACADDR_SET) 259 } 260 261 func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode uint32) error { 262 base := link.Attrs() 263 h.ensureIndex(base) 264 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 265 266 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 267 msg.Index = int32(base.Index) 268 req.AddData(msg) 269 270 linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) 271 linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) 272 inner := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 273 274 // IFLA_MACVLAN_MACADDR_MODE = mode 275 b := make([]byte, 4) 276 native.PutUint32(b, mode) 277 inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b) 278 279 // populate message with MAC addrs, if necessary 280 switch mode { 281 case nl.MACVLAN_MACADDR_ADD, nl.MACVLAN_MACADDR_DEL: 282 if len(addrs) == 1 { 283 inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0])) 284 } 285 case nl.MACVLAN_MACADDR_SET: 286 mad := inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_DATA, nil) 287 for _, addr := range addrs { 288 mad.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addr)) 289 } 290 } 291 292 req.AddData(linkInfo) 293 294 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 295 return err 296 } 297 298 // LinkSetMacvlanMode sets the mode of a macvlan or macvtap link device. 299 // Note that passthrough mode cannot be set to and from and will fail. 300 // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode 301 func LinkSetMacvlanMode(link Link, mode MacvlanMode) error { 302 return pkgHandle.LinkSetMacvlanMode(link, mode) 303 } 304 305 // LinkSetMacvlanMode sets the mode of the macvlan or macvtap link device. 306 // Note that passthrough mode cannot be set to and from and will fail. 307 // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode 308 func (h *Handle) LinkSetMacvlanMode(link Link, mode MacvlanMode) error { 309 base := link.Attrs() 310 h.ensureIndex(base) 311 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 312 313 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 314 msg.Index = int32(base.Index) 315 req.AddData(msg) 316 317 linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) 318 linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) 319 320 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 321 data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[mode])) 322 323 req.AddData(linkInfo) 324 325 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 326 return err 327 } 328 329 func BridgeSetMcastSnoop(link Link, on bool) error { 330 return pkgHandle.BridgeSetMcastSnoop(link, on) 331 } 332 333 func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error { 334 bridge := link.(*Bridge) 335 bridge.MulticastSnooping = &on 336 return h.linkModify(bridge, unix.NLM_F_ACK) 337 } 338 339 func BridgeSetVlanFiltering(link Link, on bool) error { 340 return pkgHandle.BridgeSetVlanFiltering(link, on) 341 } 342 343 func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error { 344 bridge := link.(*Bridge) 345 bridge.VlanFiltering = &on 346 return h.linkModify(bridge, unix.NLM_F_ACK) 347 } 348 349 func BridgeSetVlanDefaultPVID(link Link, pvid uint16) error { 350 return pkgHandle.BridgeSetVlanDefaultPVID(link, pvid) 351 } 352 353 func (h *Handle) BridgeSetVlanDefaultPVID(link Link, pvid uint16) error { 354 bridge := link.(*Bridge) 355 bridge.VlanDefaultPVID = &pvid 356 return h.linkModify(bridge, unix.NLM_F_ACK) 357 } 358 359 func SetPromiscOn(link Link) error { 360 return pkgHandle.SetPromiscOn(link) 361 } 362 363 func (h *Handle) SetPromiscOff(link Link) error { 364 base := link.Attrs() 365 h.ensureIndex(base) 366 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 367 368 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 369 msg.Change = unix.IFF_PROMISC 370 msg.Index = int32(base.Index) 371 req.AddData(msg) 372 373 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 374 return err 375 } 376 377 func SetPromiscOff(link Link) error { 378 return pkgHandle.SetPromiscOff(link) 379 } 380 381 // LinkSetUp enables the link device. 382 // Equivalent to: `ip link set $link up` 383 func LinkSetUp(link Link) error { 384 return pkgHandle.LinkSetUp(link) 385 } 386 387 // LinkSetUp enables the link device. 388 // Equivalent to: `ip link set $link up` 389 func (h *Handle) LinkSetUp(link Link) error { 390 base := link.Attrs() 391 h.ensureIndex(base) 392 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 393 394 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 395 msg.Change = unix.IFF_UP 396 msg.Flags = unix.IFF_UP 397 msg.Index = int32(base.Index) 398 req.AddData(msg) 399 400 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 401 return err 402 } 403 404 // LinkSetDown disables link device. 405 // Equivalent to: `ip link set $link down` 406 func LinkSetDown(link Link) error { 407 return pkgHandle.LinkSetDown(link) 408 } 409 410 // LinkSetDown disables link device. 411 // Equivalent to: `ip link set $link down` 412 func (h *Handle) LinkSetDown(link Link) error { 413 base := link.Attrs() 414 h.ensureIndex(base) 415 req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) 416 417 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 418 msg.Change = unix.IFF_UP 419 msg.Index = int32(base.Index) 420 req.AddData(msg) 421 422 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 423 return err 424 } 425 426 // LinkSetMTU sets the mtu of the link device. 427 // Equivalent to: `ip link set $link mtu $mtu` 428 func LinkSetMTU(link Link, mtu int) error { 429 return pkgHandle.LinkSetMTU(link, mtu) 430 } 431 432 // LinkSetMTU sets the mtu of the link device. 433 // Equivalent to: `ip link set $link mtu $mtu` 434 func (h *Handle) LinkSetMTU(link Link, mtu int) error { 435 base := link.Attrs() 436 h.ensureIndex(base) 437 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 438 439 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 440 msg.Index = int32(base.Index) 441 req.AddData(msg) 442 443 b := make([]byte, 4) 444 native.PutUint32(b, uint32(mtu)) 445 446 data := nl.NewRtAttr(unix.IFLA_MTU, b) 447 req.AddData(data) 448 449 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 450 return err 451 } 452 453 // LinkSetName sets the name of the link device. 454 // Equivalent to: `ip link set $link name $name` 455 func LinkSetName(link Link, name string) error { 456 return pkgHandle.LinkSetName(link, name) 457 } 458 459 // LinkSetName sets the name of the link device. 460 // Equivalent to: `ip link set $link name $name` 461 func (h *Handle) LinkSetName(link Link, name string) error { 462 base := link.Attrs() 463 h.ensureIndex(base) 464 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 465 466 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 467 msg.Index = int32(base.Index) 468 req.AddData(msg) 469 470 data := nl.NewRtAttr(unix.IFLA_IFNAME, []byte(name)) 471 req.AddData(data) 472 473 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 474 return err 475 } 476 477 // LinkSetAlias sets the alias of the link device. 478 // Equivalent to: `ip link set dev $link alias $name` 479 func LinkSetAlias(link Link, name string) error { 480 return pkgHandle.LinkSetAlias(link, name) 481 } 482 483 // LinkSetAlias sets the alias of the link device. 484 // Equivalent to: `ip link set dev $link alias $name` 485 func (h *Handle) LinkSetAlias(link Link, name string) error { 486 base := link.Attrs() 487 h.ensureIndex(base) 488 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 489 490 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 491 msg.Index = int32(base.Index) 492 req.AddData(msg) 493 494 data := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(name)) 495 req.AddData(data) 496 497 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 498 return err 499 } 500 501 // LinkAddAltName adds a new alternative name for the link device. 502 // Equivalent to: `ip link property add $link altname $name` 503 func LinkAddAltName(link Link, name string) error { 504 return pkgHandle.LinkAddAltName(link, name) 505 } 506 507 // LinkAddAltName adds a new alternative name for the link device. 508 // Equivalent to: `ip link property add $link altname $name` 509 func (h *Handle) LinkAddAltName(link Link, name string) error { 510 base := link.Attrs() 511 h.ensureIndex(base) 512 req := h.newNetlinkRequest(unix.RTM_NEWLINKPROP, unix.NLM_F_ACK) 513 514 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 515 msg.Index = int32(base.Index) 516 req.AddData(msg) 517 518 data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil) 519 data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name)) 520 521 req.AddData(data) 522 523 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 524 return err 525 } 526 527 // LinkDelAltName delete an alternative name for the link device. 528 // Equivalent to: `ip link property del $link altname $name` 529 func LinkDelAltName(link Link, name string) error { 530 return pkgHandle.LinkDelAltName(link, name) 531 } 532 533 // LinkDelAltName delete an alternative name for the link device. 534 // Equivalent to: `ip link property del $link altname $name` 535 func (h *Handle) LinkDelAltName(link Link, name string) error { 536 base := link.Attrs() 537 h.ensureIndex(base) 538 req := h.newNetlinkRequest(unix.RTM_DELLINKPROP, unix.NLM_F_ACK) 539 540 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 541 msg.Index = int32(base.Index) 542 req.AddData(msg) 543 544 data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil) 545 data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name)) 546 547 req.AddData(data) 548 549 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 550 return err 551 } 552 553 // LinkSetHardwareAddr sets the hardware address of the link device. 554 // Equivalent to: `ip link set $link address $hwaddr` 555 func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { 556 return pkgHandle.LinkSetHardwareAddr(link, hwaddr) 557 } 558 559 // LinkSetHardwareAddr sets the hardware address of the link device. 560 // Equivalent to: `ip link set $link address $hwaddr` 561 func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { 562 base := link.Attrs() 563 h.ensureIndex(base) 564 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 565 566 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 567 msg.Index = int32(base.Index) 568 req.AddData(msg) 569 570 data := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(hwaddr)) 571 req.AddData(data) 572 573 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 574 return err 575 } 576 577 // LinkSetVfHardwareAddr sets the hardware address of a vf for the link. 578 // Equivalent to: `ip link set $link vf $vf mac $hwaddr` 579 func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { 580 return pkgHandle.LinkSetVfHardwareAddr(link, vf, hwaddr) 581 } 582 583 // LinkSetVfHardwareAddr sets the hardware address of a vf for the link. 584 // Equivalent to: `ip link set $link vf $vf mac $hwaddr` 585 func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { 586 base := link.Attrs() 587 h.ensureIndex(base) 588 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 589 590 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 591 msg.Index = int32(base.Index) 592 req.AddData(msg) 593 594 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 595 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 596 vfmsg := nl.VfMac{ 597 Vf: uint32(vf), 598 } 599 copy(vfmsg.Mac[:], []byte(hwaddr)) 600 info.AddRtAttr(nl.IFLA_VF_MAC, vfmsg.Serialize()) 601 req.AddData(data) 602 603 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 604 return err 605 } 606 607 // LinkSetVfVlan sets the vlan of a vf for the link. 608 // Equivalent to: `ip link set $link vf $vf vlan $vlan` 609 func LinkSetVfVlan(link Link, vf, vlan int) error { 610 return pkgHandle.LinkSetVfVlan(link, vf, vlan) 611 } 612 613 // LinkSetVfVlan sets the vlan of a vf for the link. 614 // Equivalent to: `ip link set $link vf $vf vlan $vlan` 615 func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error { 616 base := link.Attrs() 617 h.ensureIndex(base) 618 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 619 620 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 621 msg.Index = int32(base.Index) 622 req.AddData(msg) 623 624 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 625 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 626 vfmsg := nl.VfVlan{ 627 Vf: uint32(vf), 628 Vlan: uint32(vlan), 629 } 630 info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize()) 631 req.AddData(data) 632 633 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 634 return err 635 } 636 637 // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link. 638 // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos` 639 func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { 640 return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos) 641 } 642 643 // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link. 644 // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos` 645 func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { 646 base := link.Attrs() 647 h.ensureIndex(base) 648 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 649 650 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 651 msg.Index = int32(base.Index) 652 req.AddData(msg) 653 654 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 655 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 656 vfmsg := nl.VfVlan{ 657 Vf: uint32(vf), 658 Vlan: uint32(vlan), 659 Qos: uint32(qos), 660 } 661 info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize()) 662 req.AddData(data) 663 664 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 665 return err 666 } 667 668 // LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link. 669 // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto` 670 func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error { 671 return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto) 672 } 673 674 // LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link. 675 // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto` 676 func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error { 677 base := link.Attrs() 678 h.ensureIndex(base) 679 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 680 681 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 682 msg.Index = int32(base.Index) 683 req.AddData(msg) 684 685 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 686 vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 687 vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil) 688 689 vfmsg := nl.VfVlanInfo{ 690 VfVlan: nl.VfVlan{ 691 Vf: uint32(vf), 692 Vlan: uint32(vlan), 693 Qos: uint32(qos), 694 }, 695 VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8, 696 } 697 698 vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, vfmsg.Serialize()) 699 req.AddData(data) 700 701 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 702 return err 703 } 704 705 // LinkSetVfTxRate sets the tx rate of a vf for the link. 706 // Equivalent to: `ip link set $link vf $vf rate $rate` 707 func LinkSetVfTxRate(link Link, vf, rate int) error { 708 return pkgHandle.LinkSetVfTxRate(link, vf, rate) 709 } 710 711 // LinkSetVfTxRate sets the tx rate of a vf for the link. 712 // Equivalent to: `ip link set $link vf $vf rate $rate` 713 func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { 714 base := link.Attrs() 715 h.ensureIndex(base) 716 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 717 718 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 719 msg.Index = int32(base.Index) 720 req.AddData(msg) 721 722 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 723 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 724 vfmsg := nl.VfTxRate{ 725 Vf: uint32(vf), 726 Rate: uint32(rate), 727 } 728 info.AddRtAttr(nl.IFLA_VF_TX_RATE, vfmsg.Serialize()) 729 req.AddData(data) 730 731 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 732 return err 733 } 734 735 // LinkSetVfRate sets the min and max tx rate of a vf for the link. 736 // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate` 737 func LinkSetVfRate(link Link, vf, minRate, maxRate int) error { 738 return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate) 739 } 740 741 // LinkSetVfRate sets the min and max tx rate of a vf for the link. 742 // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate` 743 func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error { 744 base := link.Attrs() 745 h.ensureIndex(base) 746 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 747 748 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 749 msg.Index = int32(base.Index) 750 req.AddData(msg) 751 752 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 753 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 754 vfmsg := nl.VfRate{ 755 Vf: uint32(vf), 756 MinTxRate: uint32(minRate), 757 MaxTxRate: uint32(maxRate), 758 } 759 info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize()) 760 req.AddData(data) 761 762 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 763 return err 764 } 765 766 // LinkSetVfState enables/disables virtual link state on a vf. 767 // Equivalent to: `ip link set $link vf $vf state $state` 768 func LinkSetVfState(link Link, vf int, state uint32) error { 769 return pkgHandle.LinkSetVfState(link, vf, state) 770 } 771 772 // LinkSetVfState enables/disables virtual link state on a vf. 773 // Equivalent to: `ip link set $link vf $vf state $state` 774 func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error { 775 base := link.Attrs() 776 h.ensureIndex(base) 777 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 778 779 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 780 msg.Index = int32(base.Index) 781 req.AddData(msg) 782 783 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 784 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 785 vfmsg := nl.VfLinkState{ 786 Vf: uint32(vf), 787 LinkState: state, 788 } 789 info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize()) 790 req.AddData(data) 791 792 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 793 return err 794 } 795 796 // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link. 797 // Equivalent to: `ip link set $link vf $vf spoofchk $check` 798 func LinkSetVfSpoofchk(link Link, vf int, check bool) error { 799 return pkgHandle.LinkSetVfSpoofchk(link, vf, check) 800 } 801 802 // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link. 803 // Equivalent to: `ip link set $link vf $vf spoofchk $check` 804 func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error { 805 var setting uint32 806 base := link.Attrs() 807 h.ensureIndex(base) 808 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 809 810 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 811 msg.Index = int32(base.Index) 812 req.AddData(msg) 813 814 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 815 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 816 if check { 817 setting = 1 818 } 819 vfmsg := nl.VfSpoofchk{ 820 Vf: uint32(vf), 821 Setting: setting, 822 } 823 info.AddRtAttr(nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize()) 824 req.AddData(data) 825 826 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 827 return err 828 } 829 830 // LinkSetVfTrust enables/disables trust state on a vf for the link. 831 // Equivalent to: `ip link set $link vf $vf trust $state` 832 func LinkSetVfTrust(link Link, vf int, state bool) error { 833 return pkgHandle.LinkSetVfTrust(link, vf, state) 834 } 835 836 // LinkSetVfTrust enables/disables trust state on a vf for the link. 837 // Equivalent to: `ip link set $link vf $vf trust $state` 838 func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error { 839 var setting uint32 840 base := link.Attrs() 841 h.ensureIndex(base) 842 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 843 844 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 845 msg.Index = int32(base.Index) 846 req.AddData(msg) 847 848 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 849 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 850 if state { 851 setting = 1 852 } 853 vfmsg := nl.VfTrust{ 854 Vf: uint32(vf), 855 Setting: setting, 856 } 857 info.AddRtAttr(nl.IFLA_VF_TRUST, vfmsg.Serialize()) 858 req.AddData(data) 859 860 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 861 return err 862 } 863 864 // LinkSetVfNodeGUID sets the node GUID of a vf for the link. 865 // Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid` 866 func LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error { 867 return pkgHandle.LinkSetVfGUID(link, vf, nodeguid, nl.IFLA_VF_IB_NODE_GUID) 868 } 869 870 // LinkSetVfPortGUID sets the port GUID of a vf for the link. 871 // Equivalent to: `ip link set dev $link vf $vf port_guid $portguid` 872 func LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error { 873 return pkgHandle.LinkSetVfGUID(link, vf, portguid, nl.IFLA_VF_IB_PORT_GUID) 874 } 875 876 // LinkSetVfGUID sets the node or port GUID of a vf for the link. 877 func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidType int) error { 878 var err error 879 var guid uint64 880 881 buf := bytes.NewBuffer(vfGuid) 882 err = binary.Read(buf, binary.BigEndian, &guid) 883 if err != nil { 884 return err 885 } 886 887 base := link.Attrs() 888 h.ensureIndex(base) 889 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 890 891 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 892 msg.Index = int32(base.Index) 893 req.AddData(msg) 894 895 data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) 896 info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) 897 vfmsg := nl.VfGUID{ 898 Vf: uint32(vf), 899 GUID: guid, 900 } 901 info.AddRtAttr(guidType, vfmsg.Serialize()) 902 req.AddData(data) 903 904 _, err = req.Execute(unix.NETLINK_ROUTE, 0) 905 return err 906 } 907 908 // LinkSetMaster sets the master of the link device. 909 // Equivalent to: `ip link set $link master $master` 910 func LinkSetMaster(link Link, master Link) error { 911 return pkgHandle.LinkSetMaster(link, master) 912 } 913 914 // LinkSetMaster sets the master of the link device. 915 // Equivalent to: `ip link set $link master $master` 916 func (h *Handle) LinkSetMaster(link Link, master Link) error { 917 index := 0 918 if master != nil { 919 masterBase := master.Attrs() 920 h.ensureIndex(masterBase) 921 index = masterBase.Index 922 } 923 if index <= 0 { 924 return fmt.Errorf("Device does not exist") 925 } 926 return h.LinkSetMasterByIndex(link, index) 927 } 928 929 // LinkSetNoMaster removes the master of the link device. 930 // Equivalent to: `ip link set $link nomaster` 931 func LinkSetNoMaster(link Link) error { 932 return pkgHandle.LinkSetNoMaster(link) 933 } 934 935 // LinkSetNoMaster removes the master of the link device. 936 // Equivalent to: `ip link set $link nomaster` 937 func (h *Handle) LinkSetNoMaster(link Link) error { 938 return h.LinkSetMasterByIndex(link, 0) 939 } 940 941 // LinkSetMasterByIndex sets the master of the link device. 942 // Equivalent to: `ip link set $link master $master` 943 func LinkSetMasterByIndex(link Link, masterIndex int) error { 944 return pkgHandle.LinkSetMasterByIndex(link, masterIndex) 945 } 946 947 // LinkSetMasterByIndex sets the master of the link device. 948 // Equivalent to: `ip link set $link master $master` 949 func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error { 950 base := link.Attrs() 951 h.ensureIndex(base) 952 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 953 954 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 955 msg.Index = int32(base.Index) 956 req.AddData(msg) 957 958 b := make([]byte, 4) 959 native.PutUint32(b, uint32(masterIndex)) 960 961 data := nl.NewRtAttr(unix.IFLA_MASTER, b) 962 req.AddData(data) 963 964 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 965 return err 966 } 967 968 // LinkSetNsPid puts the device into a new network namespace. The 969 // pid must be a pid of a running process. 970 // Equivalent to: `ip link set $link netns $pid` 971 func LinkSetNsPid(link Link, nspid int) error { 972 return pkgHandle.LinkSetNsPid(link, nspid) 973 } 974 975 // LinkSetNsPid puts the device into a new network namespace. The 976 // pid must be a pid of a running process. 977 // Equivalent to: `ip link set $link netns $pid` 978 func (h *Handle) LinkSetNsPid(link Link, nspid int) error { 979 base := link.Attrs() 980 h.ensureIndex(base) 981 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 982 983 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 984 msg.Index = int32(base.Index) 985 req.AddData(msg) 986 987 b := make([]byte, 4) 988 native.PutUint32(b, uint32(nspid)) 989 990 data := nl.NewRtAttr(unix.IFLA_NET_NS_PID, b) 991 req.AddData(data) 992 993 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 994 return err 995 } 996 997 // LinkSetNsFd puts the device into a new network namespace. The 998 // fd must be an open file descriptor to a network namespace. 999 // Similar to: `ip link set $link netns $ns` 1000 func LinkSetNsFd(link Link, fd int) error { 1001 return pkgHandle.LinkSetNsFd(link, fd) 1002 } 1003 1004 // LinkSetNsFd puts the device into a new network namespace. The 1005 // fd must be an open file descriptor to a network namespace. 1006 // Similar to: `ip link set $link netns $ns` 1007 func (h *Handle) LinkSetNsFd(link Link, fd int) error { 1008 base := link.Attrs() 1009 h.ensureIndex(base) 1010 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1011 1012 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1013 msg.Index = int32(base.Index) 1014 req.AddData(msg) 1015 1016 b := make([]byte, 4) 1017 native.PutUint32(b, uint32(fd)) 1018 1019 data := nl.NewRtAttr(unix.IFLA_NET_NS_FD, b) 1020 req.AddData(data) 1021 1022 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1023 return err 1024 } 1025 1026 // LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf 1027 // program loaded with bpf(type=BPF_PROG_TYPE_XDP) 1028 func LinkSetXdpFd(link Link, fd int) error { 1029 return LinkSetXdpFdWithFlags(link, fd, 0) 1030 } 1031 1032 // LinkSetXdpFdWithFlags adds a bpf function to the driver with the given 1033 // options. The fd must be a bpf program loaded with bpf(type=BPF_PROG_TYPE_XDP) 1034 func LinkSetXdpFdWithFlags(link Link, fd, flags int) error { 1035 base := link.Attrs() 1036 ensureIndex(base) 1037 req := nl.NewNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1038 1039 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1040 msg.Index = int32(base.Index) 1041 req.AddData(msg) 1042 1043 addXdpAttrs(&LinkXdp{Fd: fd, Flags: uint32(flags)}, req) 1044 1045 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1046 return err 1047 } 1048 1049 // LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device. 1050 // Equivalent to: `ip link set $link gso_max_segs $maxSegs` 1051 func LinkSetGSOMaxSegs(link Link, maxSegs int) error { 1052 return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs) 1053 } 1054 1055 // LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device. 1056 // Equivalent to: `ip link set $link gso_max_segs $maxSegs` 1057 func (h *Handle) LinkSetGSOMaxSegs(link Link, maxSize int) error { 1058 base := link.Attrs() 1059 h.ensureIndex(base) 1060 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1061 1062 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1063 msg.Index = int32(base.Index) 1064 req.AddData(msg) 1065 1066 b := make([]byte, 4) 1067 native.PutUint32(b, uint32(maxSize)) 1068 1069 data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, b) 1070 req.AddData(data) 1071 1072 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1073 return err 1074 } 1075 1076 // LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device. 1077 // Equivalent to: `ip link set $link gso_max_size $maxSize` 1078 func LinkSetGSOMaxSize(link Link, maxSize int) error { 1079 return pkgHandle.LinkSetGSOMaxSize(link, maxSize) 1080 } 1081 1082 // LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device. 1083 // Equivalent to: `ip link set $link gso_max_size $maxSize` 1084 func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error { 1085 base := link.Attrs() 1086 h.ensureIndex(base) 1087 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1088 1089 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1090 msg.Index = int32(base.Index) 1091 req.AddData(msg) 1092 1093 b := make([]byte, 4) 1094 native.PutUint32(b, uint32(maxSize)) 1095 1096 data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, b) 1097 req.AddData(data) 1098 1099 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1100 return err 1101 } 1102 1103 // LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device. 1104 // Equivalent to: `ip link set $link gro_max_size $maxSize` 1105 func LinkSetGROMaxSize(link Link, maxSize int) error { 1106 return pkgHandle.LinkSetGROMaxSize(link, maxSize) 1107 } 1108 1109 // LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device. 1110 // Equivalent to: `ip link set $link gro_max_size $maxSize` 1111 func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error { 1112 base := link.Attrs() 1113 h.ensureIndex(base) 1114 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1115 1116 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1117 msg.Index = int32(base.Index) 1118 req.AddData(msg) 1119 1120 b := make([]byte, 4) 1121 native.PutUint32(b, uint32(maxSize)) 1122 1123 data := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, b) 1124 req.AddData(data) 1125 1126 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1127 return err 1128 } 1129 1130 // LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device. 1131 // Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize` 1132 func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error { 1133 return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize) 1134 } 1135 1136 // LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device. 1137 // Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize` 1138 func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error { 1139 base := link.Attrs() 1140 h.ensureIndex(base) 1141 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1142 1143 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1144 msg.Index = int32(base.Index) 1145 req.AddData(msg) 1146 1147 b := make([]byte, 4) 1148 native.PutUint32(b, uint32(maxSize)) 1149 1150 data := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, b) 1151 req.AddData(data) 1152 1153 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1154 return err 1155 } 1156 1157 // LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device. 1158 // Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize` 1159 func LinkSetGROIPv4MaxSize(link Link, maxSize int) error { 1160 return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize) 1161 } 1162 1163 // LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device. 1164 // Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize` 1165 func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error { 1166 base := link.Attrs() 1167 h.ensureIndex(base) 1168 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 1169 1170 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1171 msg.Index = int32(base.Index) 1172 req.AddData(msg) 1173 1174 b := make([]byte, 4) 1175 native.PutUint32(b, uint32(maxSize)) 1176 1177 data := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, b) 1178 req.AddData(data) 1179 1180 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1181 return err 1182 } 1183 1184 func boolAttr(val bool) []byte { 1185 var v uint8 1186 if val { 1187 v = 1 1188 } 1189 return nl.Uint8Attr(v) 1190 } 1191 1192 type vxlanPortRange struct { 1193 Lo, Hi uint16 1194 } 1195 1196 func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { 1197 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1198 1199 if vxlan.FlowBased { 1200 vxlan.VxlanId = 0 1201 } 1202 1203 data.AddRtAttr(nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId))) 1204 1205 if vxlan.VtepDevIndex != 0 { 1206 data.AddRtAttr(nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex))) 1207 } 1208 if vxlan.SrcAddr != nil { 1209 ip := vxlan.SrcAddr.To4() 1210 if ip != nil { 1211 data.AddRtAttr(nl.IFLA_VXLAN_LOCAL, []byte(ip)) 1212 } else { 1213 ip = vxlan.SrcAddr.To16() 1214 if ip != nil { 1215 data.AddRtAttr(nl.IFLA_VXLAN_LOCAL6, []byte(ip)) 1216 } 1217 } 1218 } 1219 if vxlan.Group != nil { 1220 group := vxlan.Group.To4() 1221 if group != nil { 1222 data.AddRtAttr(nl.IFLA_VXLAN_GROUP, []byte(group)) 1223 } else { 1224 group = vxlan.Group.To16() 1225 if group != nil { 1226 data.AddRtAttr(nl.IFLA_VXLAN_GROUP6, []byte(group)) 1227 } 1228 } 1229 } 1230 1231 data.AddRtAttr(nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL))) 1232 data.AddRtAttr(nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS))) 1233 data.AddRtAttr(nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning)) 1234 data.AddRtAttr(nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy)) 1235 data.AddRtAttr(nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC)) 1236 data.AddRtAttr(nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss)) 1237 data.AddRtAttr(nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss)) 1238 data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx)) 1239 data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx)) 1240 1241 if vxlan.UDPCSum { 1242 data.AddRtAttr(nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum)) 1243 } 1244 if vxlan.GBP { 1245 data.AddRtAttr(nl.IFLA_VXLAN_GBP, []byte{}) 1246 } 1247 if vxlan.FlowBased { 1248 data.AddRtAttr(nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased)) 1249 } 1250 if vxlan.NoAge { 1251 data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0)) 1252 } else if vxlan.Age > 0 { 1253 data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age))) 1254 } 1255 if vxlan.Limit > 0 { 1256 data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit))) 1257 } 1258 if vxlan.Port > 0 { 1259 data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port))) 1260 } 1261 if vxlan.PortLow > 0 || vxlan.PortHigh > 0 { 1262 pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)} 1263 1264 buf := new(bytes.Buffer) 1265 binary.Write(buf, binary.BigEndian, &pr) 1266 1267 data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes()) 1268 } 1269 } 1270 1271 func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) { 1272 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1273 if bond.Mode >= 0 { 1274 data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode))) 1275 } 1276 if bond.ActiveSlave >= 0 { 1277 data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave))) 1278 } 1279 if bond.Miimon >= 0 { 1280 data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon))) 1281 } 1282 if bond.UpDelay >= 0 { 1283 data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay))) 1284 } 1285 if bond.DownDelay >= 0 { 1286 data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay))) 1287 } 1288 if bond.UseCarrier >= 0 { 1289 data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier))) 1290 } 1291 if bond.ArpInterval >= 0 { 1292 data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval))) 1293 } 1294 if bond.ArpIpTargets != nil { 1295 msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil) 1296 for i := range bond.ArpIpTargets { 1297 ip := bond.ArpIpTargets[i].To4() 1298 if ip != nil { 1299 msg.AddRtAttr(i, []byte(ip)) 1300 continue 1301 } 1302 ip = bond.ArpIpTargets[i].To16() 1303 if ip != nil { 1304 msg.AddRtAttr(i, []byte(ip)) 1305 } 1306 } 1307 } 1308 if bond.ArpValidate >= 0 { 1309 data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate))) 1310 } 1311 if bond.ArpAllTargets >= 0 { 1312 data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets))) 1313 } 1314 if bond.Primary >= 0 { 1315 data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary))) 1316 } 1317 if bond.PrimaryReselect >= 0 { 1318 data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect))) 1319 } 1320 if bond.FailOverMac >= 0 { 1321 data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac))) 1322 } 1323 if bond.XmitHashPolicy >= 0 { 1324 data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy))) 1325 } 1326 if bond.ResendIgmp >= 0 { 1327 data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp))) 1328 } 1329 if bond.NumPeerNotif >= 0 { 1330 data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif))) 1331 } 1332 if bond.AllSlavesActive >= 0 { 1333 data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive))) 1334 } 1335 if bond.MinLinks >= 0 { 1336 data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks))) 1337 } 1338 if bond.LpInterval >= 0 { 1339 data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval))) 1340 } 1341 if bond.PacketsPerSlave >= 0 { 1342 data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave))) 1343 } 1344 if bond.LacpRate >= 0 { 1345 data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate))) 1346 } 1347 if bond.AdSelect >= 0 { 1348 data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect))) 1349 } 1350 if bond.AdActorSysPrio >= 0 { 1351 data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio))) 1352 } 1353 if bond.AdUserPortKey >= 0 { 1354 data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey))) 1355 } 1356 if bond.AdActorSystem != nil { 1357 data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem)) 1358 } 1359 if bond.TlbDynamicLb >= 0 { 1360 data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb))) 1361 } 1362 } 1363 1364 func cleanupFds(fds []*os.File) { 1365 for _, f := range fds { 1366 f.Close() 1367 } 1368 } 1369 1370 // LinkAdd adds a new link device. The type and features of the device 1371 // are taken from the parameters in the link object. 1372 // Equivalent to: `ip link add $link` 1373 func LinkAdd(link Link) error { 1374 return pkgHandle.LinkAdd(link) 1375 } 1376 1377 // LinkAdd adds a new link device. The type and features of the device 1378 // are taken from the parameters in the link object. 1379 // Equivalent to: `ip link add $link` 1380 func (h *Handle) LinkAdd(link Link) error { 1381 return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) 1382 } 1383 1384 func LinkModify(link Link) error { 1385 return pkgHandle.LinkModify(link) 1386 } 1387 1388 func (h *Handle) LinkModify(link Link) error { 1389 return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK) 1390 } 1391 1392 func (h *Handle) linkModify(link Link, flags int) error { 1393 // TODO: support extra data for macvlan 1394 base := link.Attrs() 1395 1396 // if tuntap, then the name can be empty, OS will provide a name 1397 tuntap, isTuntap := link.(*Tuntap) 1398 1399 if base.Name == "" && !isTuntap { 1400 return fmt.Errorf("LinkAttrs.Name cannot be empty") 1401 } 1402 1403 if isTuntap { 1404 if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP { 1405 return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode) 1406 } 1407 1408 queues := tuntap.Queues 1409 1410 var fds []*os.File 1411 var req ifReq 1412 copy(req.Name[:15], base.Name) 1413 1414 req.Flags = uint16(tuntap.Flags) 1415 1416 if queues == 0 { //Legacy compatibility 1417 queues = 1 1418 if tuntap.Flags == 0 { 1419 req.Flags = uint16(TUNTAP_DEFAULTS) 1420 } 1421 } else { 1422 // For best peformance set Flags to TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR 1423 // when a) KVM has support for this ABI and 1424 // b) the value of the flag is queryable using the TUNGETIFF ioctl 1425 if tuntap.Flags == 0 { 1426 req.Flags = uint16(TUNTAP_MULTI_QUEUE_DEFAULTS) 1427 } 1428 } 1429 1430 req.Flags |= uint16(tuntap.Mode) 1431 const TUN = "/dev/net/tun" 1432 for i := 0; i < queues; i++ { 1433 localReq := req 1434 fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0) 1435 if err != nil { 1436 cleanupFds(fds) 1437 return err 1438 } 1439 1440 _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq))) 1441 if errno != 0 { 1442 // close the new fd 1443 unix.Close(fd) 1444 // and the already opened ones 1445 cleanupFds(fds) 1446 return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno) 1447 } 1448 1449 _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETOWNER, uintptr(tuntap.Owner)) 1450 if errno != 0 { 1451 cleanupFds(fds) 1452 return fmt.Errorf("Tuntap IOCTL TUNSETOWNER failed [%d], errno %v", i, errno) 1453 } 1454 1455 _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETGROUP, uintptr(tuntap.Group)) 1456 if errno != 0 { 1457 cleanupFds(fds) 1458 return fmt.Errorf("Tuntap IOCTL TUNSETGROUP failed [%d], errno %v", i, errno) 1459 } 1460 1461 // Set the tun device to non-blocking before use. The below comment 1462 // taken from: 1463 // 1464 // https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea 1465 // 1466 // Note there is a complication because in go, if a device node is 1467 // opened, go sets it to use nonblocking I/O. However a /dev/net/tun 1468 // doesn't work with epoll until after the TUNSETIFF ioctl has been 1469 // done. So we open the unix fd directly, do the ioctl, then put the 1470 // fd in nonblocking mode, an then finally wrap it in a os.File, 1471 // which will see the nonblocking mode and add the fd to the 1472 // pollable set, so later on when we Read() from it blocked the 1473 // calling thread in the kernel. 1474 // 1475 // See 1476 // https://github.com/golang/go/issues/30426 1477 // which got exposed in go 1.13 by the fix to 1478 // https://github.com/golang/go/issues/30624 1479 err = unix.SetNonblock(fd, true) 1480 if err != nil { 1481 cleanupFds(fds) 1482 return fmt.Errorf("Tuntap set to non-blocking failed [%d], err %v", i, err) 1483 } 1484 1485 // create the file from the file descriptor and store it 1486 file := os.NewFile(uintptr(fd), TUN) 1487 fds = append(fds, file) 1488 1489 // 1) we only care for the name of the first tap in the multi queue set 1490 // 2) if the original name was empty, the localReq has now the actual name 1491 // 1492 // In addition: 1493 // This ensures that the link name is always identical to what the kernel returns. 1494 // Not only in case of an empty name, but also when using name templates. 1495 // e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number. 1496 if i == 0 { 1497 link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00") 1498 } 1499 1500 } 1501 1502 control := func(file *os.File, f func(fd uintptr)) error { 1503 name := file.Name() 1504 conn, err := file.SyscallConn() 1505 if err != nil { 1506 return fmt.Errorf("SyscallConn() failed on %s: %v", name, err) 1507 } 1508 if err := conn.Control(f); err != nil { 1509 return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err) 1510 } 1511 return nil 1512 } 1513 1514 // only persist interface if NonPersist is NOT set 1515 if !tuntap.NonPersist { 1516 var errno syscall.Errno 1517 if err := control(fds[0], func(fd uintptr) { 1518 _, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1) 1519 }); err != nil { 1520 return err 1521 } 1522 if errno != 0 { 1523 cleanupFds(fds) 1524 return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno) 1525 } 1526 } 1527 1528 h.ensureIndex(base) 1529 1530 // can't set master during create, so set it afterwards 1531 if base.MasterIndex != 0 { 1532 // TODO: verify MasterIndex is actually a bridge? 1533 err := h.LinkSetMasterByIndex(link, base.MasterIndex) 1534 if err != nil { 1535 // un-persist (e.g. allow the interface to be removed) the tuntap 1536 // should not hurt if not set prior, condition might be not needed 1537 if !tuntap.NonPersist { 1538 // ignore error 1539 _ = control(fds[0], func(fd uintptr) { 1540 _, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0) 1541 }) 1542 } 1543 cleanupFds(fds) 1544 return err 1545 } 1546 } 1547 1548 if tuntap.Queues == 0 { 1549 cleanupFds(fds) 1550 } else { 1551 tuntap.Fds = fds 1552 } 1553 1554 return nil 1555 } 1556 1557 req := h.newNetlinkRequest(unix.RTM_NEWLINK, flags) 1558 1559 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1560 // TODO: make it shorter 1561 if base.Flags&net.FlagUp != 0 { 1562 msg.Change = unix.IFF_UP 1563 msg.Flags = unix.IFF_UP 1564 } 1565 if base.Flags&net.FlagBroadcast != 0 { 1566 msg.Change |= unix.IFF_BROADCAST 1567 msg.Flags |= unix.IFF_BROADCAST 1568 } 1569 if base.Flags&net.FlagLoopback != 0 { 1570 msg.Change |= unix.IFF_LOOPBACK 1571 msg.Flags |= unix.IFF_LOOPBACK 1572 } 1573 if base.Flags&net.FlagPointToPoint != 0 { 1574 msg.Change |= unix.IFF_POINTOPOINT 1575 msg.Flags |= unix.IFF_POINTOPOINT 1576 } 1577 if base.Flags&net.FlagMulticast != 0 { 1578 msg.Change |= unix.IFF_MULTICAST 1579 msg.Flags |= unix.IFF_MULTICAST 1580 } 1581 if base.Index != 0 { 1582 msg.Index = int32(base.Index) 1583 } 1584 1585 req.AddData(msg) 1586 1587 if base.ParentIndex != 0 { 1588 b := make([]byte, 4) 1589 native.PutUint32(b, uint32(base.ParentIndex)) 1590 data := nl.NewRtAttr(unix.IFLA_LINK, b) 1591 req.AddData(data) 1592 } else if link.Type() == "ipvlan" || link.Type() == "ipoib" { 1593 return fmt.Errorf("Can't create %s link without ParentIndex", link.Type()) 1594 } 1595 1596 nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name)) 1597 req.AddData(nameData) 1598 1599 if base.Alias != "" { 1600 alias := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(base.Alias)) 1601 req.AddData(alias) 1602 } 1603 1604 if base.MTU > 0 { 1605 mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) 1606 req.AddData(mtu) 1607 } 1608 1609 if base.TxQLen >= 0 { 1610 qlen := nl.NewRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) 1611 req.AddData(qlen) 1612 } 1613 1614 if base.HardwareAddr != nil { 1615 hwaddr := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(base.HardwareAddr)) 1616 req.AddData(hwaddr) 1617 } 1618 1619 if base.NumTxQueues > 0 { 1620 txqueues := nl.NewRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) 1621 req.AddData(txqueues) 1622 } 1623 1624 if base.NumRxQueues > 0 { 1625 rxqueues := nl.NewRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) 1626 req.AddData(rxqueues) 1627 } 1628 1629 if base.GSOMaxSegs > 0 { 1630 gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs)) 1631 req.AddData(gsoAttr) 1632 } 1633 1634 if base.GSOMaxSize > 0 { 1635 gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize)) 1636 req.AddData(gsoAttr) 1637 } 1638 1639 if base.GROMaxSize > 0 { 1640 groAttr := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, nl.Uint32Attr(base.GROMaxSize)) 1641 req.AddData(groAttr) 1642 } 1643 1644 if base.GSOIPv4MaxSize > 0 { 1645 gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GSOIPv4MaxSize)) 1646 req.AddData(gsoAttr) 1647 } 1648 1649 if base.GROIPv4MaxSize > 0 { 1650 groAttr := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GROIPv4MaxSize)) 1651 req.AddData(groAttr) 1652 } 1653 1654 if base.Group > 0 { 1655 groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group)) 1656 req.AddData(groupAttr) 1657 } 1658 1659 if base.Namespace != nil { 1660 var attr *nl.RtAttr 1661 switch ns := base.Namespace.(type) { 1662 case NsPid: 1663 val := nl.Uint32Attr(uint32(ns)) 1664 attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val) 1665 case NsFd: 1666 val := nl.Uint32Attr(uint32(ns)) 1667 attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val) 1668 } 1669 1670 req.AddData(attr) 1671 } 1672 1673 if base.Xdp != nil { 1674 addXdpAttrs(base.Xdp, req) 1675 } 1676 1677 linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) 1678 linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) 1679 1680 switch link := link.(type) { 1681 case *Vlan: 1682 b := make([]byte, 2) 1683 native.PutUint16(b, uint16(link.VlanId)) 1684 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1685 data.AddRtAttr(nl.IFLA_VLAN_ID, b) 1686 var vlanFlags uint32 1687 var vlanFlagsMask uint32 1688 if link.ReorderHdr != nil { 1689 vlanFlagsMask |= nl.VLAN_FLAG_REORDER_HDR 1690 if *link.ReorderHdr { 1691 vlanFlags |= nl.VLAN_FLAG_REORDER_HDR 1692 } else { 1693 vlanFlags &= ^uint32(nl.VLAN_FLAG_REORDER_HDR) 1694 } 1695 } 1696 if link.Gvrp != nil { 1697 vlanFlagsMask |= nl.VLAN_FLAG_GVRP 1698 if *link.Gvrp { 1699 vlanFlags |= nl.VLAN_FLAG_GVRP 1700 } else { 1701 vlanFlags &= ^uint32(nl.VLAN_FLAG_GVRP) 1702 } 1703 } 1704 if link.Mvrp != nil { 1705 vlanFlagsMask |= nl.VLAN_FLAG_MVRP 1706 if *link.Mvrp { 1707 vlanFlags |= nl.VLAN_FLAG_MVRP 1708 } else { 1709 vlanFlags &= ^uint32(nl.VLAN_FLAG_MVRP) 1710 } 1711 } 1712 if link.LooseBinding != nil { 1713 vlanFlagsMask |= nl.VLAN_FLAG_LOOSE_BINDING 1714 if *link.LooseBinding { 1715 vlanFlags |= nl.VLAN_FLAG_LOOSE_BINDING 1716 } else { 1717 vlanFlags &= ^uint32(nl.VLAN_FLAG_LOOSE_BINDING) 1718 } 1719 } 1720 if link.BridgeBinding != nil { 1721 vlanFlagsMask |= nl.VLAN_FLAG_BRIDGE_BINDING 1722 if *link.BridgeBinding { 1723 vlanFlags |= nl.VLAN_FLAG_BRIDGE_BINDING 1724 } else { 1725 vlanFlags &= ^uint32(nl.VLAN_FLAG_BRIDGE_BINDING) 1726 } 1727 } 1728 1729 buf := &bytes.Buffer{} 1730 buf.Write(nl.Uint32Attr(vlanFlags)) 1731 buf.Write(nl.Uint32Attr(vlanFlagsMask)) 1732 data.AddRtAttr(nl.IFLA_VLAN_FLAGS, buf.Bytes()) 1733 1734 if link.IngressQosMap != nil { 1735 ingressMap := data.AddRtAttr(nl.IFLA_VLAN_INGRESS_QOS, nil) 1736 for from, to := range link.IngressQosMap { 1737 buf := &bytes.Buffer{} 1738 buf.Write(nl.Uint32Attr(from)) 1739 buf.Write(nl.Uint32Attr(to)) 1740 ingressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes()) 1741 } 1742 } 1743 1744 if link.EgressQosMap != nil { 1745 egressMap := data.AddRtAttr(nl.IFLA_VLAN_EGRESS_QOS, nil) 1746 for from, to := range link.EgressQosMap { 1747 buf := &bytes.Buffer{} 1748 buf.Write(nl.Uint32Attr(from)) 1749 buf.Write(nl.Uint32Attr(to)) 1750 egressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes()) 1751 } 1752 } 1753 1754 if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN { 1755 data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol))) 1756 } 1757 case *Netkit: 1758 if err := addNetkitAttrs(link, linkInfo, flags); err != nil { 1759 return err 1760 } 1761 case *Veth: 1762 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1763 peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil) 1764 nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC) 1765 peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName)) 1766 1767 if link.PeerTxQLen >= 0 { 1768 peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(link.PeerTxQLen))) 1769 } else if base.TxQLen >= 0 { 1770 peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) 1771 } 1772 if link.PeerNumTxQueues > 0 { 1773 peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(link.PeerNumTxQueues)) 1774 } else if base.NumTxQueues > 0 { 1775 peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) 1776 } 1777 if link.PeerNumRxQueues > 0 { 1778 peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(link.PeerNumRxQueues)) 1779 } else if base.NumRxQueues > 0 { 1780 peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) 1781 } 1782 if link.PeerMTU > 0 { 1783 peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(link.PeerMTU)) 1784 } else if base.MTU > 0 { 1785 peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) 1786 } 1787 if link.PeerHardwareAddr != nil { 1788 peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr)) 1789 } 1790 if link.PeerNamespace != nil { 1791 switch ns := link.PeerNamespace.(type) { 1792 case NsPid: 1793 val := nl.Uint32Attr(uint32(ns)) 1794 peer.AddRtAttr(unix.IFLA_NET_NS_PID, val) 1795 case NsFd: 1796 val := nl.Uint32Attr(uint32(ns)) 1797 peer.AddRtAttr(unix.IFLA_NET_NS_FD, val) 1798 } 1799 } 1800 case *Vxlan: 1801 addVxlanAttrs(link, linkInfo) 1802 case *Bond: 1803 addBondAttrs(link, linkInfo) 1804 case *IPVlan: 1805 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1806 data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) 1807 data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) 1808 case *IPVtap: 1809 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 1810 data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) 1811 data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) 1812 case *Macvlan: 1813 addMacvlanAttrs(link, linkInfo) 1814 case *Macvtap: 1815 addMacvtapAttrs(link, linkInfo) 1816 case *Geneve: 1817 addGeneveAttrs(link, linkInfo) 1818 case *Gretap: 1819 addGretapAttrs(link, linkInfo) 1820 case *Iptun: 1821 addIptunAttrs(link, linkInfo) 1822 case *Ip6tnl: 1823 addIp6tnlAttrs(link, linkInfo) 1824 case *Sittun: 1825 addSittunAttrs(link, linkInfo) 1826 case *Gretun: 1827 addGretunAttrs(link, linkInfo) 1828 case *Vti: 1829 addVtiAttrs(link, linkInfo) 1830 case *Vrf: 1831 addVrfAttrs(link, linkInfo) 1832 case *Bridge: 1833 addBridgeAttrs(link, linkInfo) 1834 case *GTP: 1835 addGTPAttrs(link, linkInfo) 1836 case *Xfrmi: 1837 addXfrmiAttrs(link, linkInfo) 1838 case *IPoIB: 1839 addIPoIBAttrs(link, linkInfo) 1840 case *BareUDP: 1841 addBareUDPAttrs(link, linkInfo) 1842 } 1843 1844 req.AddData(linkInfo) 1845 1846 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1847 if err != nil { 1848 return err 1849 } 1850 1851 h.ensureIndex(base) 1852 1853 // can't set master during create, so set it afterwards 1854 if base.MasterIndex != 0 { 1855 // TODO: verify MasterIndex is actually a bridge? 1856 return h.LinkSetMasterByIndex(link, base.MasterIndex) 1857 } 1858 return nil 1859 } 1860 1861 // LinkDel deletes link device. Either Index or Name must be set in 1862 // the link object for it to be deleted. The other values are ignored. 1863 // Equivalent to: `ip link del $link` 1864 func LinkDel(link Link) error { 1865 return pkgHandle.LinkDel(link) 1866 } 1867 1868 // LinkDel deletes link device. Either Index or Name must be set in 1869 // the link object for it to be deleted. The other values are ignored. 1870 // Equivalent to: `ip link del $link` 1871 func (h *Handle) LinkDel(link Link) error { 1872 base := link.Attrs() 1873 1874 h.ensureIndex(base) 1875 1876 req := h.newNetlinkRequest(unix.RTM_DELLINK, unix.NLM_F_ACK) 1877 1878 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1879 msg.Index = int32(base.Index) 1880 req.AddData(msg) 1881 1882 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 1883 return err 1884 } 1885 1886 func (h *Handle) linkByNameDump(name string) (Link, error) { 1887 links, executeErr := h.LinkList() 1888 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 1889 return nil, executeErr 1890 } 1891 1892 for _, link := range links { 1893 if link.Attrs().Name == name { 1894 return link, executeErr 1895 } 1896 1897 // support finding interfaces also via altnames 1898 for _, altName := range link.Attrs().AltNames { 1899 if altName == name { 1900 return link, executeErr 1901 } 1902 } 1903 } 1904 return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)} 1905 } 1906 1907 func (h *Handle) linkByAliasDump(alias string) (Link, error) { 1908 links, executeErr := h.LinkList() 1909 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 1910 return nil, executeErr 1911 } 1912 1913 for _, link := range links { 1914 if link.Attrs().Alias == alias { 1915 return link, executeErr 1916 } 1917 } 1918 return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)} 1919 } 1920 1921 // LinkByName finds a link by name and returns a pointer to the object. 1922 // 1923 // If the kernel doesn't support IFLA_IFNAME, this method will fall back to 1924 // filtering a dump of all link names. In this case, if the returned error is 1925 // [ErrDumpInterrupted] the result may be missing or outdated. 1926 func LinkByName(name string) (Link, error) { 1927 return pkgHandle.LinkByName(name) 1928 } 1929 1930 // LinkByName finds a link by name and returns a pointer to the object. 1931 // 1932 // If the kernel doesn't support IFLA_IFNAME, this method will fall back to 1933 // filtering a dump of all link names. In this case, if the returned error is 1934 // [ErrDumpInterrupted] the result may be missing or outdated. 1935 func (h *Handle) LinkByName(name string) (Link, error) { 1936 if h.lookupByDump { 1937 return h.linkByNameDump(name) 1938 } 1939 1940 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) 1941 1942 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1943 req.AddData(msg) 1944 1945 attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) 1946 req.AddData(attr) 1947 1948 nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name)) 1949 if len(name) > 15 { 1950 nameData = nl.NewRtAttr(unix.IFLA_ALT_IFNAME, nl.ZeroTerminated(name)) 1951 } 1952 req.AddData(nameData) 1953 1954 link, err := execGetLink(req) 1955 if err == unix.EINVAL { 1956 // older kernels don't support looking up via IFLA_IFNAME 1957 // so fall back to dumping all links 1958 h.lookupByDump = true 1959 return h.linkByNameDump(name) 1960 } 1961 1962 return link, err 1963 } 1964 1965 // LinkByAlias finds a link by its alias and returns a pointer to the object. 1966 // If there are multiple links with the alias it returns the first one 1967 // 1968 // If the kernel doesn't support IFLA_IFALIAS, this method will fall back to 1969 // filtering a dump of all link names. In this case, if the returned error is 1970 // [ErrDumpInterrupted] the result may be missing or outdated. 1971 func LinkByAlias(alias string) (Link, error) { 1972 return pkgHandle.LinkByAlias(alias) 1973 } 1974 1975 // LinkByAlias finds a link by its alias and returns a pointer to the object. 1976 // If there are multiple links with the alias it returns the first one 1977 // 1978 // If the kernel doesn't support IFLA_IFALIAS, this method will fall back to 1979 // filtering a dump of all link names. In this case, if the returned error is 1980 // [ErrDumpInterrupted] the result may be missing or outdated. 1981 func (h *Handle) LinkByAlias(alias string) (Link, error) { 1982 if h.lookupByDump { 1983 return h.linkByAliasDump(alias) 1984 } 1985 1986 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) 1987 1988 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 1989 req.AddData(msg) 1990 1991 attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) 1992 req.AddData(attr) 1993 1994 nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias)) 1995 req.AddData(nameData) 1996 1997 link, err := execGetLink(req) 1998 if err == unix.EINVAL { 1999 // older kernels don't support looking up via IFLA_IFALIAS 2000 // so fall back to dumping all links 2001 h.lookupByDump = true 2002 return h.linkByAliasDump(alias) 2003 } 2004 2005 return link, err 2006 } 2007 2008 // LinkByIndex finds a link by index and returns a pointer to the object. 2009 func LinkByIndex(index int) (Link, error) { 2010 return pkgHandle.LinkByIndex(index) 2011 } 2012 2013 // LinkByIndex finds a link by index and returns a pointer to the object. 2014 func (h *Handle) LinkByIndex(index int) (Link, error) { 2015 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) 2016 2017 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2018 msg.Index = int32(index) 2019 req.AddData(msg) 2020 attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) 2021 req.AddData(attr) 2022 2023 return execGetLink(req) 2024 } 2025 2026 func execGetLink(req *nl.NetlinkRequest) (Link, error) { 2027 msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) 2028 if err != nil { 2029 if errno, ok := err.(syscall.Errno); ok { 2030 if errno == unix.ENODEV { 2031 return nil, LinkNotFoundError{fmt.Errorf("Link not found")} 2032 } 2033 } 2034 return nil, err 2035 } 2036 2037 switch { 2038 case len(msgs) == 0: 2039 return nil, LinkNotFoundError{fmt.Errorf("Link not found")} 2040 2041 case len(msgs) == 1: 2042 return LinkDeserialize(nil, msgs[0]) 2043 2044 default: 2045 return nil, fmt.Errorf("More than one link found") 2046 } 2047 } 2048 2049 // LinkDeserialize deserializes a raw message received from netlink into 2050 // a link object. 2051 func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { 2052 msg := nl.DeserializeIfInfomsg(m) 2053 2054 attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 2055 if err != nil { 2056 return nil, err 2057 } 2058 2059 base := NewLinkAttrs() 2060 base.Index = int(msg.Index) 2061 base.RawFlags = msg.Flags 2062 base.Flags = linkFlags(msg.Flags) 2063 base.EncapType = msg.EncapType() 2064 base.NetNsID = -1 2065 if msg.Flags&unix.IFF_ALLMULTI != 0 { 2066 base.Allmulti = 1 2067 } 2068 if msg.Flags&unix.IFF_MULTICAST != 0 { 2069 base.Multi = 1 2070 } 2071 2072 var ( 2073 link Link 2074 stats32 *LinkStatistics32 2075 stats64 *LinkStatistics64 2076 linkType string 2077 linkSlave LinkSlave 2078 slaveType string 2079 ) 2080 for _, attr := range attrs { 2081 switch attr.Attr.Type { 2082 case unix.IFLA_LINKINFO: 2083 infos, err := nl.ParseRouteAttr(attr.Value) 2084 if err != nil { 2085 return nil, err 2086 } 2087 for _, info := range infos { 2088 switch info.Attr.Type { 2089 case nl.IFLA_INFO_KIND: 2090 linkType = string(info.Value[:len(info.Value)-1]) 2091 switch linkType { 2092 case "dummy": 2093 link = &Dummy{} 2094 case "ifb": 2095 link = &Ifb{} 2096 case "bridge": 2097 link = &Bridge{} 2098 case "vlan": 2099 link = &Vlan{} 2100 case "netkit": 2101 link = &Netkit{} 2102 case "veth": 2103 link = &Veth{} 2104 case "wireguard": 2105 link = &Wireguard{} 2106 case "vxlan": 2107 link = &Vxlan{} 2108 case "bond": 2109 link = &Bond{} 2110 case "ipvlan": 2111 link = &IPVlan{} 2112 case "ipvtap": 2113 link = &IPVtap{} 2114 case "macvlan": 2115 link = &Macvlan{} 2116 case "macvtap": 2117 link = &Macvtap{} 2118 case "geneve": 2119 link = &Geneve{} 2120 case "gretap": 2121 link = &Gretap{} 2122 case "ip6gretap": 2123 link = &Gretap{} 2124 case "ipip": 2125 link = &Iptun{} 2126 case "ip6tnl": 2127 link = &Ip6tnl{} 2128 case "sit": 2129 link = &Sittun{} 2130 case "gre": 2131 link = &Gretun{} 2132 case "ip6gre": 2133 link = &Gretun{} 2134 case "vti", "vti6": 2135 link = &Vti{} 2136 case "vrf": 2137 link = &Vrf{} 2138 case "gtp": 2139 link = >P{} 2140 case "xfrm": 2141 link = &Xfrmi{} 2142 case "tun": 2143 link = &Tuntap{} 2144 case "ipoib": 2145 link = &IPoIB{} 2146 case "can": 2147 link = &Can{} 2148 case "bareudp": 2149 link = &BareUDP{} 2150 default: 2151 link = &GenericLink{LinkType: linkType} 2152 } 2153 case nl.IFLA_INFO_DATA: 2154 data, err := nl.ParseRouteAttr(info.Value) 2155 if err != nil { 2156 return nil, err 2157 } 2158 switch linkType { 2159 case "netkit": 2160 parseNetkitData(link, data) 2161 case "vlan": 2162 parseVlanData(link, data) 2163 case "vxlan": 2164 parseVxlanData(link, data) 2165 case "bond": 2166 parseBondData(link, data) 2167 case "ipvlan": 2168 parseIPVlanData(link, data) 2169 case "ipvtap": 2170 parseIPVtapData(link, data) 2171 case "macvlan": 2172 parseMacvlanData(link, data) 2173 case "macvtap": 2174 parseMacvtapData(link, data) 2175 case "geneve": 2176 parseGeneveData(link, data) 2177 case "gretap": 2178 parseGretapData(link, data) 2179 case "ip6gretap": 2180 parseGretapData(link, data) 2181 case "ipip": 2182 parseIptunData(link, data) 2183 case "ip6tnl": 2184 parseIp6tnlData(link, data) 2185 case "sit": 2186 parseSittunData(link, data) 2187 case "gre": 2188 parseGretunData(link, data) 2189 case "ip6gre": 2190 parseGretunData(link, data) 2191 case "vti", "vti6": 2192 parseVtiData(link, data) 2193 case "vrf": 2194 parseVrfData(link, data) 2195 case "bridge": 2196 parseBridgeData(link, data) 2197 case "gtp": 2198 parseGTPData(link, data) 2199 case "xfrm": 2200 parseXfrmiData(link, data) 2201 case "tun": 2202 parseTuntapData(link, data) 2203 case "ipoib": 2204 parseIPoIBData(link, data) 2205 case "can": 2206 parseCanData(link, data) 2207 case "bareudp": 2208 parseBareUDPData(link, data) 2209 } 2210 2211 case nl.IFLA_INFO_SLAVE_KIND: 2212 slaveType = string(info.Value[:len(info.Value)-1]) 2213 switch slaveType { 2214 case "bond": 2215 linkSlave = &BondSlave{} 2216 case "vrf": 2217 linkSlave = &VrfSlave{} 2218 } 2219 2220 case nl.IFLA_INFO_SLAVE_DATA: 2221 switch slaveType { 2222 case "bond": 2223 data, err := nl.ParseRouteAttr(info.Value) 2224 if err != nil { 2225 return nil, err 2226 } 2227 parseBondSlaveData(linkSlave, data) 2228 case "vrf": 2229 data, err := nl.ParseRouteAttr(info.Value) 2230 if err != nil { 2231 return nil, err 2232 } 2233 parseVrfSlaveData(linkSlave, data) 2234 } 2235 } 2236 } 2237 case unix.IFLA_ADDRESS: 2238 var nonzero bool 2239 for _, b := range attr.Value { 2240 if b != 0 { 2241 nonzero = true 2242 } 2243 } 2244 if nonzero { 2245 base.HardwareAddr = attr.Value[:] 2246 } 2247 case unix.IFLA_IFNAME: 2248 base.Name = string(attr.Value[:len(attr.Value)-1]) 2249 case unix.IFLA_MTU: 2250 base.MTU = int(native.Uint32(attr.Value[0:4])) 2251 case unix.IFLA_PROMISCUITY: 2252 base.Promisc = int(native.Uint32(attr.Value[0:4])) 2253 case unix.IFLA_LINK: 2254 base.ParentIndex = int(native.Uint32(attr.Value[0:4])) 2255 case unix.IFLA_MASTER: 2256 base.MasterIndex = int(native.Uint32(attr.Value[0:4])) 2257 case unix.IFLA_TXQLEN: 2258 base.TxQLen = int(native.Uint32(attr.Value[0:4])) 2259 case unix.IFLA_IFALIAS: 2260 base.Alias = string(attr.Value[:len(attr.Value)-1]) 2261 case unix.IFLA_STATS: 2262 stats32 = new(LinkStatistics32) 2263 if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil { 2264 return nil, err 2265 } 2266 case unix.IFLA_STATS64: 2267 stats64 = new(LinkStatistics64) 2268 if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil { 2269 return nil, err 2270 } 2271 case unix.IFLA_XDP: 2272 xdp, err := parseLinkXdp(attr.Value[:]) 2273 if err != nil { 2274 return nil, err 2275 } 2276 base.Xdp = xdp 2277 case unix.IFLA_PROTINFO | unix.NLA_F_NESTED: 2278 if hdr != nil && hdr.Type == unix.RTM_NEWLINK && 2279 msg.Family == unix.AF_BRIDGE { 2280 attrs, err := nl.ParseRouteAttr(attr.Value[:]) 2281 if err != nil { 2282 return nil, err 2283 } 2284 protinfo := parseProtinfo(attrs) 2285 base.Protinfo = &protinfo 2286 } 2287 case unix.IFLA_PROP_LIST | unix.NLA_F_NESTED: 2288 attrs, err := nl.ParseRouteAttr(attr.Value[:]) 2289 if err != nil { 2290 return nil, err 2291 } 2292 2293 base.AltNames = []string{} 2294 for _, attr := range attrs { 2295 if attr.Attr.Type == unix.IFLA_ALT_IFNAME { 2296 base.AltNames = append(base.AltNames, nl.BytesToString(attr.Value)) 2297 } 2298 } 2299 case unix.IFLA_OPERSTATE: 2300 base.OperState = LinkOperState(uint8(attr.Value[0])) 2301 case unix.IFLA_PHYS_SWITCH_ID: 2302 base.PhysSwitchID = int(native.Uint32(attr.Value[0:4])) 2303 case unix.IFLA_LINK_NETNSID: 2304 base.NetNsID = int(native.Uint32(attr.Value[0:4])) 2305 case unix.IFLA_TSO_MAX_SEGS: 2306 base.TSOMaxSegs = native.Uint32(attr.Value[0:4]) 2307 case unix.IFLA_TSO_MAX_SIZE: 2308 base.TSOMaxSize = native.Uint32(attr.Value[0:4]) 2309 case unix.IFLA_GSO_MAX_SEGS: 2310 base.GSOMaxSegs = native.Uint32(attr.Value[0:4]) 2311 case unix.IFLA_GSO_MAX_SIZE: 2312 base.GSOMaxSize = native.Uint32(attr.Value[0:4]) 2313 case unix.IFLA_GRO_MAX_SIZE: 2314 base.GROMaxSize = native.Uint32(attr.Value[0:4]) 2315 case unix.IFLA_GSO_IPV4_MAX_SIZE: 2316 base.GSOIPv4MaxSize = native.Uint32(attr.Value[0:4]) 2317 case unix.IFLA_GRO_IPV4_MAX_SIZE: 2318 base.GROIPv4MaxSize = native.Uint32(attr.Value[0:4]) 2319 case unix.IFLA_VFINFO_LIST: 2320 data, err := nl.ParseRouteAttr(attr.Value) 2321 if err != nil { 2322 return nil, err 2323 } 2324 vfs, err := parseVfInfoList(data) 2325 if err != nil { 2326 return nil, err 2327 } 2328 base.Vfs = vfs 2329 case unix.IFLA_NUM_TX_QUEUES: 2330 base.NumTxQueues = int(native.Uint32(attr.Value[0:4])) 2331 case unix.IFLA_NUM_RX_QUEUES: 2332 base.NumRxQueues = int(native.Uint32(attr.Value[0:4])) 2333 case unix.IFLA_GROUP: 2334 base.Group = native.Uint32(attr.Value[0:4]) 2335 case unix.IFLA_PERM_ADDRESS: 2336 for _, b := range attr.Value { 2337 if b != 0 { 2338 base.PermHWAddr = attr.Value[:] 2339 break 2340 } 2341 } 2342 case unix.IFLA_PARENT_DEV_NAME: 2343 base.ParentDev = string(attr.Value[:len(attr.Value)-1]) 2344 case unix.IFLA_PARENT_DEV_BUS_NAME: 2345 base.ParentDevBus = string(attr.Value[:len(attr.Value)-1]) 2346 } 2347 } 2348 2349 if stats64 != nil { 2350 base.Statistics = (*LinkStatistics)(stats64) 2351 } else if stats32 != nil { 2352 base.Statistics = (*LinkStatistics)(stats32.to64()) 2353 } 2354 2355 // Links that don't have IFLA_INFO_KIND are hardware devices 2356 if link == nil { 2357 link = &Device{} 2358 } 2359 *link.Attrs() = base 2360 link.Attrs().Slave = linkSlave 2361 2362 // If the tuntap attributes are not updated by netlink due to 2363 // an older driver, use sysfs 2364 if link != nil && linkType == "tun" { 2365 tuntap := link.(*Tuntap) 2366 2367 if tuntap.Mode == 0 { 2368 ifname := tuntap.Attrs().Name 2369 if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil { 2370 2371 if flags&unix.IFF_TUN != 0 { 2372 tuntap.Mode = unix.IFF_TUN 2373 } else if flags&unix.IFF_TAP != 0 { 2374 tuntap.Mode = unix.IFF_TAP 2375 } 2376 2377 tuntap.NonPersist = false 2378 if flags&unix.IFF_PERSIST == 0 { 2379 tuntap.NonPersist = true 2380 } 2381 } 2382 2383 // The sysfs interface for owner/group returns -1 for root user, instead of returning 0. 2384 // So explicitly check for negative value, before assigning the owner uid/gid. 2385 if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 { 2386 tuntap.Owner = uint32(owner) 2387 } 2388 2389 if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 { 2390 tuntap.Group = uint32(group) 2391 } 2392 } 2393 } 2394 2395 return link, nil 2396 } 2397 2398 func readSysPropAsInt64(ifname, prop string) (int64, error) { 2399 fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop) 2400 contents, err := ioutil.ReadFile(fname) 2401 if err != nil { 2402 return 0, err 2403 } 2404 2405 num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64) 2406 if err == nil { 2407 return num, nil 2408 } 2409 2410 return 0, err 2411 } 2412 2413 // LinkList gets a list of link devices. 2414 // Equivalent to: `ip link show` 2415 func LinkList() ([]Link, error) { 2416 return pkgHandle.LinkList() 2417 } 2418 2419 // LinkList gets a list of link devices. 2420 // Equivalent to: `ip link show` 2421 // 2422 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 2423 // or incomplete. 2424 func (h *Handle) LinkList() ([]Link, error) { 2425 // NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need 2426 // to get the message ourselves to parse link type. 2427 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) 2428 2429 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2430 req.AddData(msg) 2431 attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) 2432 req.AddData(attr) 2433 2434 msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) 2435 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 2436 return nil, executeErr 2437 } 2438 2439 var res []Link 2440 for _, m := range msgs { 2441 link, err := LinkDeserialize(nil, m) 2442 if err != nil { 2443 return nil, err 2444 } 2445 res = append(res, link) 2446 } 2447 2448 return res, executeErr 2449 } 2450 2451 // LinkUpdate is used to pass information back from LinkSubscribe() 2452 type LinkUpdate struct { 2453 nl.IfInfomsg 2454 Header unix.NlMsghdr 2455 Link 2456 } 2457 2458 // LinkSubscribe takes a chan down which notifications will be sent 2459 // when links change. Close the 'done' chan to stop subscription. 2460 func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { 2461 return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false) 2462 } 2463 2464 // LinkSubscribeAt works like LinkSubscribe plus it allows the caller 2465 // to choose the network namespace in which to subscribe (ns). 2466 func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error { 2467 return linkSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false) 2468 } 2469 2470 // LinkSubscribeOptions contains a set of options to use with 2471 // LinkSubscribeWithOptions. 2472 type LinkSubscribeOptions struct { 2473 Namespace *netns.NsHandle 2474 ErrorCallback func(error) 2475 ListExisting bool 2476 ReceiveBufferSize int 2477 ReceiveBufferForceSize bool 2478 ReceiveTimeout *unix.Timeval 2479 } 2480 2481 // LinkSubscribeWithOptions work like LinkSubscribe but enable to 2482 // provide additional options to modify the behavior. Currently, the 2483 // namespace can be provided as well as an error callback. 2484 // 2485 // When options.ListExisting is true, options.ErrorCallback may be 2486 // called with [ErrDumpInterrupted] to indicate that results from 2487 // the initial dump of links may be inconsistent or incomplete. 2488 func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error { 2489 if options.Namespace == nil { 2490 none := netns.None() 2491 options.Namespace = &none 2492 } 2493 return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, 2494 options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize) 2495 } 2496 2497 func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool, 2498 rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error { 2499 s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK) 2500 if err != nil { 2501 return err 2502 } 2503 if rcvTimeout != nil { 2504 if err := s.SetReceiveTimeout(rcvTimeout); err != nil { 2505 return err 2506 } 2507 } 2508 if rcvbuf != 0 { 2509 err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce) 2510 if err != nil { 2511 return err 2512 } 2513 } 2514 if done != nil { 2515 go func() { 2516 <-done 2517 s.Close() 2518 }() 2519 } 2520 if listExisting { 2521 req := pkgHandle.newNetlinkRequest(unix.RTM_GETLINK, 2522 unix.NLM_F_DUMP) 2523 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2524 req.AddData(msg) 2525 if err := s.Send(req); err != nil { 2526 return err 2527 } 2528 } 2529 go func() { 2530 defer close(ch) 2531 for { 2532 msgs, from, err := s.Receive() 2533 if err != nil { 2534 if cberr != nil { 2535 cberr(fmt.Errorf("Receive failed: %v", 2536 err)) 2537 } 2538 return 2539 } 2540 if from.Pid != nl.PidKernel { 2541 if cberr != nil { 2542 cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) 2543 } 2544 continue 2545 } 2546 for _, m := range msgs { 2547 if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 && cberr != nil { 2548 cberr(ErrDumpInterrupted) 2549 } 2550 if m.Header.Type == unix.NLMSG_DONE { 2551 continue 2552 } 2553 if m.Header.Type == unix.NLMSG_ERROR { 2554 error := int32(native.Uint32(m.Data[0:4])) 2555 if error == 0 { 2556 continue 2557 } 2558 if cberr != nil { 2559 cberr(fmt.Errorf("error message: %v", 2560 syscall.Errno(-error))) 2561 } 2562 continue 2563 } 2564 ifmsg := nl.DeserializeIfInfomsg(m.Data) 2565 header := unix.NlMsghdr(m.Header) 2566 link, err := LinkDeserialize(&header, m.Data) 2567 if err != nil { 2568 if cberr != nil { 2569 cberr(err) 2570 } 2571 continue 2572 } 2573 ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link} 2574 } 2575 } 2576 }() 2577 2578 return nil 2579 } 2580 2581 func LinkSetHairpin(link Link, mode bool) error { 2582 return pkgHandle.LinkSetHairpin(link, mode) 2583 } 2584 2585 func (h *Handle) LinkSetHairpin(link Link, mode bool) error { 2586 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE) 2587 } 2588 2589 func LinkSetGuard(link Link, mode bool) error { 2590 return pkgHandle.LinkSetGuard(link, mode) 2591 } 2592 2593 func (h *Handle) LinkSetGuard(link Link, mode bool) error { 2594 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD) 2595 } 2596 2597 // LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface 2598 func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error { 2599 return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask) 2600 } 2601 2602 // LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface 2603 func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error { 2604 return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK) 2605 } 2606 2607 func LinkSetFastLeave(link Link, mode bool) error { 2608 return pkgHandle.LinkSetFastLeave(link, mode) 2609 } 2610 2611 func (h *Handle) LinkSetFastLeave(link Link, mode bool) error { 2612 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE) 2613 } 2614 2615 func LinkSetLearning(link Link, mode bool) error { 2616 return pkgHandle.LinkSetLearning(link, mode) 2617 } 2618 2619 func (h *Handle) LinkSetLearning(link Link, mode bool) error { 2620 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING) 2621 } 2622 2623 func LinkSetVlanTunnel(link Link, mode bool) error { 2624 return pkgHandle.LinkSetVlanTunnel(link, mode) 2625 } 2626 2627 func (h *Handle) LinkSetVlanTunnel(link Link, mode bool) error { 2628 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_VLAN_TUNNEL) 2629 } 2630 2631 func LinkSetRootBlock(link Link, mode bool) error { 2632 return pkgHandle.LinkSetRootBlock(link, mode) 2633 } 2634 2635 func (h *Handle) LinkSetRootBlock(link Link, mode bool) error { 2636 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT) 2637 } 2638 2639 func LinkSetFlood(link Link, mode bool) error { 2640 return pkgHandle.LinkSetFlood(link, mode) 2641 } 2642 2643 func (h *Handle) LinkSetFlood(link Link, mode bool) error { 2644 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) 2645 } 2646 2647 func LinkSetIsolated(link Link, mode bool) error { 2648 return pkgHandle.LinkSetIsolated(link, mode) 2649 } 2650 2651 func (h *Handle) LinkSetIsolated(link Link, mode bool) error { 2652 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_ISOLATED) 2653 } 2654 2655 func LinkSetBrProxyArp(link Link, mode bool) error { 2656 return pkgHandle.LinkSetBrProxyArp(link, mode) 2657 } 2658 2659 func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error { 2660 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP) 2661 } 2662 2663 func LinkSetBrProxyArpWiFi(link Link, mode bool) error { 2664 return pkgHandle.LinkSetBrProxyArpWiFi(link, mode) 2665 } 2666 2667 func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { 2668 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) 2669 } 2670 2671 func LinkSetBrNeighSuppress(link Link, mode bool) error { 2672 return pkgHandle.LinkSetBrNeighSuppress(link, mode) 2673 } 2674 2675 func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error { 2676 return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS) 2677 } 2678 2679 func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error { 2680 base := link.Attrs() 2681 h.ensureIndex(base) 2682 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 2683 2684 msg := nl.NewIfInfomsg(unix.AF_BRIDGE) 2685 msg.Index = int32(base.Index) 2686 req.AddData(msg) 2687 2688 br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil) 2689 br.AddRtAttr(attr, val) 2690 req.AddData(br) 2691 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 2692 if err != nil { 2693 return err 2694 } 2695 return nil 2696 } 2697 func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { 2698 return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr) 2699 } 2700 2701 // LinkSetTxQLen sets the transaction queue length for the link. 2702 // Equivalent to: `ip link set $link txqlen $qlen` 2703 func LinkSetTxQLen(link Link, qlen int) error { 2704 return pkgHandle.LinkSetTxQLen(link, qlen) 2705 } 2706 2707 // LinkSetTxQLen sets the transaction queue length for the link. 2708 // Equivalent to: `ip link set $link txqlen $qlen` 2709 func (h *Handle) LinkSetTxQLen(link Link, qlen int) error { 2710 base := link.Attrs() 2711 h.ensureIndex(base) 2712 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 2713 2714 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2715 msg.Index = int32(base.Index) 2716 req.AddData(msg) 2717 2718 b := make([]byte, 4) 2719 native.PutUint32(b, uint32(qlen)) 2720 2721 data := nl.NewRtAttr(unix.IFLA_TXQLEN, b) 2722 req.AddData(data) 2723 2724 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 2725 return err 2726 } 2727 2728 // LinkSetGroup sets the link group id which can be used to perform mass actions 2729 // with iproute2 as well use it as a reference in nft filters. 2730 // Equivalent to: `ip link set $link group $id` 2731 func LinkSetGroup(link Link, group int) error { 2732 return pkgHandle.LinkSetGroup(link, group) 2733 } 2734 2735 // LinkSetGroup sets the link group id which can be used to perform mass actions 2736 // with iproute2 as well use it as a reference in nft filters. 2737 // Equivalent to: `ip link set $link group $id` 2738 func (h *Handle) LinkSetGroup(link Link, group int) error { 2739 base := link.Attrs() 2740 h.ensureIndex(base) 2741 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 2742 2743 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2744 msg.Index = int32(base.Index) 2745 req.AddData(msg) 2746 2747 b := make([]byte, 4) 2748 native.PutUint32(b, uint32(group)) 2749 2750 data := nl.NewRtAttr(unix.IFLA_GROUP, b) 2751 req.AddData(data) 2752 2753 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 2754 return err 2755 } 2756 2757 // LinkSetIP6AddrGenMode sets the IPv6 address generation mode of the link device. 2758 // Equivalent to: `ip link set $link addrgenmode $mode` 2759 func LinkSetIP6AddrGenMode(link Link, mode int) error { 2760 return pkgHandle.LinkSetIP6AddrGenMode(link, mode) 2761 } 2762 2763 // LinkSetIP6AddrGenMode sets the IPv6 address generation mode of the link device. 2764 // Equivalent to: `ip link set $link addrgenmode $mode` 2765 func (h *Handle) LinkSetIP6AddrGenMode(link Link, mode int) error { 2766 base := link.Attrs() 2767 h.ensureIndex(base) 2768 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 2769 2770 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2771 msg.Index = int32(base.Index) 2772 req.AddData(msg) 2773 2774 b := make([]byte, 1) 2775 b[0] = uint8(mode) 2776 2777 data := nl.NewRtAttr(unix.IFLA_INET6_ADDR_GEN_MODE, b) 2778 af := nl.NewRtAttr(unix.AF_INET6, data.Serialize()) 2779 spec := nl.NewRtAttr(unix.IFLA_AF_SPEC, af.Serialize()) 2780 req.AddData(spec) 2781 2782 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 2783 return err 2784 } 2785 2786 func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error { 2787 if nk.Mode != NETKIT_MODE_L2 && (nk.LinkAttrs.HardwareAddr != nil || nk.peerLinkAttrs.HardwareAddr != nil) { 2788 return fmt.Errorf("netkit only allows setting Ethernet in L2 mode") 2789 } 2790 2791 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 2792 // Kernel will return error if trying to change the mode of an existing netkit device 2793 data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode))) 2794 data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy))) 2795 data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy))) 2796 data.AddRtAttr(nl.IFLA_NETKIT_SCRUB, nl.Uint32Attr(uint32(nk.Scrub))) 2797 data.AddRtAttr(nl.IFLA_NETKIT_PEER_SCRUB, nl.Uint32Attr(uint32(nk.PeerScrub))) 2798 2799 if (flag & unix.NLM_F_EXCL) == 0 { 2800 // Modifying peer link attributes will not take effect 2801 return nil 2802 } 2803 2804 peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil) 2805 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 2806 if nk.peerLinkAttrs.Flags&net.FlagUp != 0 { 2807 msg.Change = unix.IFF_UP 2808 msg.Flags = unix.IFF_UP 2809 } 2810 if nk.peerLinkAttrs.Index != 0 { 2811 msg.Index = int32(nk.peerLinkAttrs.Index) 2812 } 2813 peer.AddChild(msg) 2814 if nk.peerLinkAttrs.Name != "" { 2815 peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name)) 2816 } 2817 if nk.peerLinkAttrs.MTU > 0 { 2818 peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU))) 2819 } 2820 if nk.peerLinkAttrs.GSOMaxSegs > 0 { 2821 peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs)) 2822 } 2823 if nk.peerLinkAttrs.GSOMaxSize > 0 { 2824 peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize)) 2825 } 2826 if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 { 2827 peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize)) 2828 } 2829 if nk.peerLinkAttrs.GROIPv4MaxSize > 0 { 2830 peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize)) 2831 } 2832 if nk.peerLinkAttrs.Namespace != nil { 2833 switch ns := nk.peerLinkAttrs.Namespace.(type) { 2834 case NsPid: 2835 peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns))) 2836 case NsFd: 2837 peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns))) 2838 } 2839 } 2840 if nk.peerLinkAttrs.HardwareAddr != nil { 2841 peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(nk.peerLinkAttrs.HardwareAddr)) 2842 } 2843 return nil 2844 } 2845 2846 func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) { 2847 netkit := link.(*Netkit) 2848 for _, datum := range data { 2849 switch datum.Attr.Type { 2850 case nl.IFLA_NETKIT_PRIMARY: 2851 isPrimary := datum.Value[0:1][0] 2852 if isPrimary != 0 { 2853 netkit.isPrimary = true 2854 } 2855 case nl.IFLA_NETKIT_MODE: 2856 netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4])) 2857 case nl.IFLA_NETKIT_POLICY: 2858 netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4])) 2859 case nl.IFLA_NETKIT_PEER_POLICY: 2860 netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4])) 2861 case nl.IFLA_NETKIT_SCRUB: 2862 netkit.supportsScrub = true 2863 netkit.Scrub = NetkitScrub(native.Uint32(datum.Value[0:4])) 2864 case nl.IFLA_NETKIT_PEER_SCRUB: 2865 netkit.supportsScrub = true 2866 netkit.PeerScrub = NetkitScrub(native.Uint32(datum.Value[0:4])) 2867 } 2868 } 2869 } 2870 2871 func parseVlanQosMap(data []byte) map[uint32]uint32 { 2872 values, err := nl.ParseRouteAttr(data) 2873 if err != nil { 2874 return nil 2875 } 2876 2877 qosMap := make(map[uint32]uint32) 2878 2879 for _, value := range values { 2880 switch value.Attr.Type { 2881 case nl.IFLA_VLAN_QOS_MAPPING: 2882 from := native.Uint32(value.Value[:4]) 2883 to := native.Uint32(value.Value[4:]) 2884 qosMap[from] = to 2885 } 2886 } 2887 2888 return qosMap 2889 } 2890 2891 func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { 2892 vlan := link.(*Vlan) 2893 for _, datum := range data { 2894 switch datum.Attr.Type { 2895 case nl.IFLA_VLAN_ID: 2896 vlan.VlanId = int(native.Uint16(datum.Value[0:2])) 2897 case nl.IFLA_VLAN_FLAGS: 2898 flags := native.Uint32(datum.Value[0:4]) 2899 trueVal := true 2900 falseVal := false 2901 if flags&nl.VLAN_FLAG_REORDER_HDR != 0 { 2902 vlan.ReorderHdr = &trueVal 2903 } else { 2904 vlan.ReorderHdr = &falseVal 2905 } 2906 if flags&nl.VLAN_FLAG_GVRP != 0 { 2907 vlan.Gvrp = &trueVal 2908 } else { 2909 vlan.Gvrp = &falseVal 2910 } 2911 if flags&nl.VLAN_FLAG_LOOSE_BINDING != 0 { 2912 vlan.LooseBinding = &trueVal 2913 } else { 2914 vlan.LooseBinding = &falseVal 2915 } 2916 if flags&nl.VLAN_FLAG_MVRP != 0 { 2917 vlan.Mvrp = &trueVal 2918 } else { 2919 vlan.Mvrp = &falseVal 2920 } 2921 if flags&nl.VLAN_FLAG_BRIDGE_BINDING != 0 { 2922 vlan.BridgeBinding = &trueVal 2923 } else { 2924 vlan.BridgeBinding = &falseVal 2925 } 2926 case nl.IFLA_VLAN_EGRESS_QOS: 2927 vlan.EgressQosMap = parseVlanQosMap(datum.Value) 2928 case nl.IFLA_VLAN_INGRESS_QOS: 2929 vlan.IngressQosMap = parseVlanQosMap(datum.Value) 2930 case nl.IFLA_VLAN_PROTOCOL: 2931 vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2]))) 2932 } 2933 } 2934 } 2935 2936 func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { 2937 vxlan := link.(*Vxlan) 2938 for _, datum := range data { 2939 // NOTE(vish): Apparently some messages can be sent with no value. 2940 // We special case GBP here to not change existing 2941 // functionality. It appears that GBP sends a datum.Value 2942 // of null. 2943 if len(datum.Value) == 0 && datum.Attr.Type != nl.IFLA_VXLAN_GBP { 2944 continue 2945 } 2946 switch datum.Attr.Type { 2947 case nl.IFLA_VXLAN_ID: 2948 vxlan.VxlanId = int(native.Uint32(datum.Value[0:4])) 2949 case nl.IFLA_VXLAN_LINK: 2950 vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4])) 2951 case nl.IFLA_VXLAN_LOCAL: 2952 vxlan.SrcAddr = net.IP(datum.Value[0:4]) 2953 case nl.IFLA_VXLAN_LOCAL6: 2954 vxlan.SrcAddr = net.IP(datum.Value[0:16]) 2955 case nl.IFLA_VXLAN_GROUP: 2956 vxlan.Group = net.IP(datum.Value[0:4]) 2957 case nl.IFLA_VXLAN_GROUP6: 2958 vxlan.Group = net.IP(datum.Value[0:16]) 2959 case nl.IFLA_VXLAN_TTL: 2960 vxlan.TTL = int(datum.Value[0]) 2961 case nl.IFLA_VXLAN_TOS: 2962 vxlan.TOS = int(datum.Value[0]) 2963 case nl.IFLA_VXLAN_LEARNING: 2964 vxlan.Learning = int8(datum.Value[0]) != 0 2965 case nl.IFLA_VXLAN_PROXY: 2966 vxlan.Proxy = int8(datum.Value[0]) != 0 2967 case nl.IFLA_VXLAN_RSC: 2968 vxlan.RSC = int8(datum.Value[0]) != 0 2969 case nl.IFLA_VXLAN_L2MISS: 2970 vxlan.L2miss = int8(datum.Value[0]) != 0 2971 case nl.IFLA_VXLAN_L3MISS: 2972 vxlan.L3miss = int8(datum.Value[0]) != 0 2973 case nl.IFLA_VXLAN_UDP_CSUM: 2974 vxlan.UDPCSum = int8(datum.Value[0]) != 0 2975 case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX: 2976 vxlan.UDP6ZeroCSumTx = int8(datum.Value[0]) != 0 2977 case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX: 2978 vxlan.UDP6ZeroCSumRx = int8(datum.Value[0]) != 0 2979 case nl.IFLA_VXLAN_GBP: 2980 vxlan.GBP = true 2981 case nl.IFLA_VXLAN_FLOWBASED: 2982 vxlan.FlowBased = int8(datum.Value[0]) != 0 2983 case nl.IFLA_VXLAN_AGEING: 2984 vxlan.Age = int(native.Uint32(datum.Value[0:4])) 2985 vxlan.NoAge = vxlan.Age == 0 2986 case nl.IFLA_VXLAN_LIMIT: 2987 vxlan.Limit = int(native.Uint32(datum.Value[0:4])) 2988 case nl.IFLA_VXLAN_PORT: 2989 vxlan.Port = int(ntohs(datum.Value[0:2])) 2990 case nl.IFLA_VXLAN_PORT_RANGE: 2991 buf := bytes.NewBuffer(datum.Value[0:4]) 2992 var pr vxlanPortRange 2993 if binary.Read(buf, binary.BigEndian, &pr) == nil { 2994 vxlan.PortLow = int(pr.Lo) 2995 vxlan.PortHigh = int(pr.Hi) 2996 } 2997 } 2998 } 2999 } 3000 3001 func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { 3002 bond := link.(*Bond) 3003 for i := range data { 3004 switch data[i].Attr.Type { 3005 case nl.IFLA_BOND_MODE: 3006 bond.Mode = BondMode(data[i].Value[0]) 3007 case nl.IFLA_BOND_ACTIVE_SLAVE: 3008 bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4])) 3009 case nl.IFLA_BOND_MIIMON: 3010 bond.Miimon = int(native.Uint32(data[i].Value[0:4])) 3011 case nl.IFLA_BOND_UPDELAY: 3012 bond.UpDelay = int(native.Uint32(data[i].Value[0:4])) 3013 case nl.IFLA_BOND_DOWNDELAY: 3014 bond.DownDelay = int(native.Uint32(data[i].Value[0:4])) 3015 case nl.IFLA_BOND_USE_CARRIER: 3016 bond.UseCarrier = int(data[i].Value[0]) 3017 case nl.IFLA_BOND_ARP_INTERVAL: 3018 bond.ArpInterval = int(native.Uint32(data[i].Value[0:4])) 3019 case nl.IFLA_BOND_ARP_IP_TARGET: 3020 bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value) 3021 case nl.IFLA_BOND_ARP_VALIDATE: 3022 bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4])) 3023 case nl.IFLA_BOND_ARP_ALL_TARGETS: 3024 bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4])) 3025 case nl.IFLA_BOND_PRIMARY: 3026 bond.Primary = int(native.Uint32(data[i].Value[0:4])) 3027 case nl.IFLA_BOND_PRIMARY_RESELECT: 3028 bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0]) 3029 case nl.IFLA_BOND_FAIL_OVER_MAC: 3030 bond.FailOverMac = BondFailOverMac(data[i].Value[0]) 3031 case nl.IFLA_BOND_XMIT_HASH_POLICY: 3032 bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0]) 3033 case nl.IFLA_BOND_RESEND_IGMP: 3034 bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4])) 3035 case nl.IFLA_BOND_NUM_PEER_NOTIF: 3036 bond.NumPeerNotif = int(data[i].Value[0]) 3037 case nl.IFLA_BOND_ALL_SLAVES_ACTIVE: 3038 bond.AllSlavesActive = int(data[i].Value[0]) 3039 case nl.IFLA_BOND_MIN_LINKS: 3040 bond.MinLinks = int(native.Uint32(data[i].Value[0:4])) 3041 case nl.IFLA_BOND_LP_INTERVAL: 3042 bond.LpInterval = int(native.Uint32(data[i].Value[0:4])) 3043 case nl.IFLA_BOND_PACKETS_PER_SLAVE: 3044 bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4])) 3045 case nl.IFLA_BOND_AD_LACP_RATE: 3046 bond.LacpRate = BondLacpRate(data[i].Value[0]) 3047 case nl.IFLA_BOND_AD_SELECT: 3048 bond.AdSelect = BondAdSelect(data[i].Value[0]) 3049 case nl.IFLA_BOND_AD_INFO: 3050 // TODO: implement 3051 case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO: 3052 bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2])) 3053 case nl.IFLA_BOND_AD_USER_PORT_KEY: 3054 bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2])) 3055 case nl.IFLA_BOND_AD_ACTOR_SYSTEM: 3056 bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6]) 3057 case nl.IFLA_BOND_TLB_DYNAMIC_LB: 3058 bond.TlbDynamicLb = int(data[i].Value[0]) 3059 } 3060 } 3061 } 3062 3063 func parseBondArpIpTargets(value []byte) []net.IP { 3064 data, err := nl.ParseRouteAttr(value) 3065 if err != nil { 3066 return nil 3067 } 3068 3069 targets := []net.IP{} 3070 for i := range data { 3071 target := net.IP(data[i].Value) 3072 if ip := target.To4(); ip != nil { 3073 targets = append(targets, ip) 3074 continue 3075 } 3076 if ip := target.To16(); ip != nil { 3077 targets = append(targets, ip) 3078 } 3079 } 3080 3081 return targets 3082 } 3083 3084 func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) { 3085 data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) 3086 3087 data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State))) 3088 data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus))) 3089 data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount)) 3090 data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId)) 3091 data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId)) 3092 data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState)) 3093 data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState)) 3094 3095 if mac := bondSlave.PermHardwareAddr; mac != nil { 3096 data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac)) 3097 } 3098 } 3099 3100 func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { 3101 bondSlave := slave.(*BondSlave) 3102 for i := range data { 3103 switch data[i].Attr.Type { 3104 case nl.IFLA_BOND_SLAVE_STATE: 3105 bondSlave.State = BondSlaveState(data[i].Value[0]) 3106 case nl.IFLA_BOND_SLAVE_MII_STATUS: 3107 bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0]) 3108 case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT: 3109 bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4]) 3110 case nl.IFLA_BOND_SLAVE_PERM_HWADDR: 3111 bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6]) 3112 case nl.IFLA_BOND_SLAVE_QUEUE_ID: 3113 bondSlave.QueueId = native.Uint16(data[i].Value[0:2]) 3114 case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID: 3115 bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2]) 3116 case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE: 3117 bondSlave.AdActorOperPortState = uint8(data[i].Value[0]) 3118 case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE: 3119 bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2]) 3120 } 3121 } 3122 } 3123 3124 func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { 3125 vrfSlave := slave.(*VrfSlave) 3126 for i := range data { 3127 switch data[i].Attr.Type { 3128 case nl.IFLA_BOND_SLAVE_STATE: 3129 vrfSlave.Table = native.Uint32(data[i].Value[0:4]) 3130 } 3131 } 3132 } 3133 3134 func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { 3135 ipv := link.(*IPVlan) 3136 for _, datum := range data { 3137 switch datum.Attr.Type { 3138 case nl.IFLA_IPVLAN_MODE: 3139 ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) 3140 case nl.IFLA_IPVLAN_FLAG: 3141 ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4])) 3142 } 3143 } 3144 } 3145 3146 func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) { 3147 ipv := link.(*IPVtap) 3148 for _, datum := range data { 3149 switch datum.Attr.Type { 3150 case nl.IFLA_IPVLAN_MODE: 3151 ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) 3152 case nl.IFLA_IPVLAN_FLAG: 3153 ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4])) 3154 } 3155 } 3156 } 3157 3158 func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) { 3159 addMacvlanAttrs(&macvtap.Macvlan, linkInfo) 3160 } 3161 3162 func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { 3163 macv := link.(*Macvtap) 3164 parseMacvlanData(&macv.Macvlan, data) 3165 } 3166 3167 func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) { 3168 var data *nl.RtAttr 3169 3170 if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 { 3171 data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3172 } 3173 3174 if macvlan.Mode != MACVLAN_MODE_DEFAULT { 3175 data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode])) 3176 } 3177 if macvlan.BCQueueLen > 0 { 3178 data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen)) 3179 } 3180 } 3181 3182 func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { 3183 macv := link.(*Macvlan) 3184 for _, datum := range data { 3185 switch datum.Attr.Type { 3186 case nl.IFLA_MACVLAN_MODE: 3187 switch native.Uint32(datum.Value[0:4]) { 3188 case nl.MACVLAN_MODE_PRIVATE: 3189 macv.Mode = MACVLAN_MODE_PRIVATE 3190 case nl.MACVLAN_MODE_VEPA: 3191 macv.Mode = MACVLAN_MODE_VEPA 3192 case nl.MACVLAN_MODE_BRIDGE: 3193 macv.Mode = MACVLAN_MODE_BRIDGE 3194 case nl.MACVLAN_MODE_PASSTHRU: 3195 macv.Mode = MACVLAN_MODE_PASSTHRU 3196 case nl.MACVLAN_MODE_SOURCE: 3197 macv.Mode = MACVLAN_MODE_SOURCE 3198 } 3199 case nl.IFLA_MACVLAN_MACADDR_COUNT: 3200 macv.MACAddrs = make([]net.HardwareAddr, 0, int(native.Uint32(datum.Value[0:4]))) 3201 case nl.IFLA_MACVLAN_MACADDR_DATA: 3202 macs, err := nl.ParseRouteAttr(datum.Value[:]) 3203 if err != nil { 3204 panic(fmt.Sprintf("failed to ParseRouteAttr for IFLA_MACVLAN_MACADDR_DATA: %v", err)) 3205 } 3206 for _, macDatum := range macs { 3207 macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6])) 3208 } 3209 case nl.IFLA_MACVLAN_BC_QUEUE_LEN: 3210 macv.BCQueueLen = native.Uint32(datum.Value[0:4]) 3211 case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED: 3212 macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4]) 3213 } 3214 } 3215 } 3216 3217 func linkFlags(rawFlags uint32) net.Flags { 3218 var f net.Flags 3219 if rawFlags&unix.IFF_UP != 0 { 3220 f |= net.FlagUp 3221 } 3222 if rawFlags&unix.IFF_BROADCAST != 0 { 3223 f |= net.FlagBroadcast 3224 } 3225 if rawFlags&unix.IFF_LOOPBACK != 0 { 3226 f |= net.FlagLoopback 3227 } 3228 if rawFlags&unix.IFF_POINTOPOINT != 0 { 3229 f |= net.FlagPointToPoint 3230 } 3231 if rawFlags&unix.IFF_MULTICAST != 0 { 3232 f |= net.FlagMulticast 3233 } 3234 if rawFlags&unix.IFF_RUNNING != 0 { 3235 f |= net.FlagRunning 3236 } 3237 return f 3238 } 3239 3240 type genevePortRange struct { 3241 Lo, Hi uint16 3242 } 3243 3244 func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) { 3245 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3246 3247 if geneve.InnerProtoInherit { 3248 data.AddRtAttr(nl.IFLA_GENEVE_INNER_PROTO_INHERIT, []byte{}) 3249 } 3250 3251 if geneve.FlowBased { 3252 geneve.ID = 0 3253 data.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, []byte{}) 3254 } 3255 3256 if ip := geneve.Remote; ip != nil { 3257 if ip4 := ip.To4(); ip4 != nil { 3258 data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4()) 3259 } else { 3260 data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip)) 3261 } 3262 } 3263 3264 if geneve.ID != 0 { 3265 data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID)) 3266 } 3267 3268 if geneve.Dport != 0 { 3269 data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport)) 3270 } 3271 3272 if geneve.Ttl != 0 { 3273 data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl)) 3274 } 3275 3276 if geneve.Tos != 0 { 3277 data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos)) 3278 } 3279 3280 if geneve.PortLow > 0 || geneve.PortHigh > 0 { 3281 pr := genevePortRange{uint16(geneve.PortLow), uint16(geneve.PortHigh)} 3282 3283 buf := new(bytes.Buffer) 3284 binary.Write(buf, binary.BigEndian, &pr) 3285 3286 data.AddRtAttr(nl.IFLA_GENEVE_PORT_RANGE, buf.Bytes()) 3287 } 3288 3289 data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df))) 3290 } 3291 3292 func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) { 3293 geneve := link.(*Geneve) 3294 for _, datum := range data { 3295 switch datum.Attr.Type { 3296 case nl.IFLA_GENEVE_ID: 3297 geneve.ID = native.Uint32(datum.Value[0:4]) 3298 case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6: 3299 geneve.Remote = datum.Value 3300 case nl.IFLA_GENEVE_PORT: 3301 geneve.Dport = ntohs(datum.Value[0:2]) 3302 case nl.IFLA_GENEVE_TTL: 3303 geneve.Ttl = uint8(datum.Value[0]) 3304 case nl.IFLA_GENEVE_TOS: 3305 geneve.Tos = uint8(datum.Value[0]) 3306 case nl.IFLA_GENEVE_COLLECT_METADATA: 3307 geneve.FlowBased = true 3308 case nl.IFLA_GENEVE_INNER_PROTO_INHERIT: 3309 geneve.InnerProtoInherit = true 3310 case nl.IFLA_GENEVE_PORT_RANGE: 3311 buf := bytes.NewBuffer(datum.Value[0:4]) 3312 var pr genevePortRange 3313 if binary.Read(buf, binary.BigEndian, &pr) == nil { 3314 geneve.PortLow = int(pr.Lo) 3315 geneve.PortHigh = int(pr.Hi) 3316 } 3317 } 3318 } 3319 } 3320 3321 func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { 3322 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3323 3324 if gretap.FlowBased { 3325 // In flow based mode, no other attributes need to be configured 3326 data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{}) 3327 return 3328 } 3329 3330 if ip := gretap.Local; ip != nil { 3331 if ip.To4() != nil { 3332 ip = ip.To4() 3333 } 3334 data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) 3335 } 3336 3337 if ip := gretap.Remote; ip != nil { 3338 if ip.To4() != nil { 3339 ip = ip.To4() 3340 } 3341 data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) 3342 } 3343 3344 if gretap.IKey != 0 { 3345 data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey)) 3346 gretap.IFlags |= uint16(nl.GRE_KEY) 3347 } 3348 3349 if gretap.OKey != 0 { 3350 data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey)) 3351 gretap.OFlags |= uint16(nl.GRE_KEY) 3352 } 3353 3354 data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags)) 3355 data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags)) 3356 3357 if gretap.Link != 0 { 3358 data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link)) 3359 } 3360 3361 data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc)) 3362 data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl)) 3363 data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos)) 3364 data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType)) 3365 data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags)) 3366 data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport)) 3367 data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport)) 3368 } 3369 3370 func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { 3371 gre := link.(*Gretap) 3372 for _, datum := range data { 3373 switch datum.Attr.Type { 3374 case nl.IFLA_GRE_OKEY: 3375 gre.IKey = ntohl(datum.Value[0:4]) 3376 case nl.IFLA_GRE_IKEY: 3377 gre.OKey = ntohl(datum.Value[0:4]) 3378 case nl.IFLA_GRE_LOCAL: 3379 gre.Local = net.IP(datum.Value) 3380 case nl.IFLA_GRE_REMOTE: 3381 gre.Remote = net.IP(datum.Value) 3382 case nl.IFLA_GRE_ENCAP_SPORT: 3383 gre.EncapSport = ntohs(datum.Value[0:2]) 3384 case nl.IFLA_GRE_ENCAP_DPORT: 3385 gre.EncapDport = ntohs(datum.Value[0:2]) 3386 case nl.IFLA_GRE_IFLAGS: 3387 gre.IFlags = ntohs(datum.Value[0:2]) 3388 case nl.IFLA_GRE_OFLAGS: 3389 gre.OFlags = ntohs(datum.Value[0:2]) 3390 case nl.IFLA_GRE_TTL: 3391 gre.Ttl = uint8(datum.Value[0]) 3392 case nl.IFLA_GRE_TOS: 3393 gre.Tos = uint8(datum.Value[0]) 3394 case nl.IFLA_GRE_PMTUDISC: 3395 gre.PMtuDisc = uint8(datum.Value[0]) 3396 case nl.IFLA_GRE_ENCAP_TYPE: 3397 gre.EncapType = native.Uint16(datum.Value[0:2]) 3398 case nl.IFLA_GRE_ENCAP_FLAGS: 3399 gre.EncapFlags = native.Uint16(datum.Value[0:2]) 3400 case nl.IFLA_GRE_COLLECT_METADATA: 3401 gre.FlowBased = true 3402 } 3403 } 3404 } 3405 3406 func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) { 3407 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3408 3409 if gre.FlowBased { 3410 // In flow based mode, no other attributes need to be configured 3411 data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{}) 3412 return 3413 } 3414 3415 if ip := gre.Local; ip != nil { 3416 if ip.To4() != nil { 3417 ip = ip.To4() 3418 } 3419 data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) 3420 } 3421 3422 if ip := gre.Remote; ip != nil { 3423 if ip.To4() != nil { 3424 ip = ip.To4() 3425 } 3426 data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) 3427 } 3428 3429 if gre.IKey != 0 { 3430 data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey)) 3431 gre.IFlags |= uint16(nl.GRE_KEY) 3432 } 3433 3434 if gre.OKey != 0 { 3435 data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey)) 3436 gre.OFlags |= uint16(nl.GRE_KEY) 3437 } 3438 3439 data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags)) 3440 data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags)) 3441 3442 if gre.Link != 0 { 3443 data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link)) 3444 } 3445 3446 data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc)) 3447 data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl)) 3448 data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos)) 3449 data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType)) 3450 data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags)) 3451 data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport)) 3452 data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport)) 3453 } 3454 3455 func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) { 3456 gre := link.(*Gretun) 3457 for _, datum := range data { 3458 switch datum.Attr.Type { 3459 case nl.IFLA_GRE_IKEY: 3460 gre.IKey = ntohl(datum.Value[0:4]) 3461 case nl.IFLA_GRE_OKEY: 3462 gre.OKey = ntohl(datum.Value[0:4]) 3463 case nl.IFLA_GRE_LOCAL: 3464 gre.Local = net.IP(datum.Value) 3465 case nl.IFLA_GRE_REMOTE: 3466 gre.Remote = net.IP(datum.Value) 3467 case nl.IFLA_GRE_IFLAGS: 3468 gre.IFlags = ntohs(datum.Value[0:2]) 3469 case nl.IFLA_GRE_OFLAGS: 3470 gre.OFlags = ntohs(datum.Value[0:2]) 3471 case nl.IFLA_GRE_TTL: 3472 gre.Ttl = uint8(datum.Value[0]) 3473 case nl.IFLA_GRE_TOS: 3474 gre.Tos = uint8(datum.Value[0]) 3475 case nl.IFLA_GRE_PMTUDISC: 3476 gre.PMtuDisc = uint8(datum.Value[0]) 3477 case nl.IFLA_GRE_ENCAP_TYPE: 3478 gre.EncapType = native.Uint16(datum.Value[0:2]) 3479 case nl.IFLA_GRE_ENCAP_FLAGS: 3480 gre.EncapFlags = native.Uint16(datum.Value[0:2]) 3481 case nl.IFLA_GRE_ENCAP_SPORT: 3482 gre.EncapSport = ntohs(datum.Value[0:2]) 3483 case nl.IFLA_GRE_ENCAP_DPORT: 3484 gre.EncapDport = ntohs(datum.Value[0:2]) 3485 case nl.IFLA_GRE_COLLECT_METADATA: 3486 gre.FlowBased = true 3487 } 3488 } 3489 } 3490 3491 func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { 3492 attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil) 3493 b := make([]byte, 4) 3494 native.PutUint32(b, uint32(xdp.Fd)) 3495 attrs.AddRtAttr(nl.IFLA_XDP_FD, b) 3496 if xdp.Flags != 0 { 3497 b := make([]byte, 4) 3498 native.PutUint32(b, xdp.Flags) 3499 attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b) 3500 } 3501 req.AddData(attrs) 3502 } 3503 3504 func parseLinkXdp(data []byte) (*LinkXdp, error) { 3505 attrs, err := nl.ParseRouteAttr(data) 3506 if err != nil { 3507 return nil, err 3508 } 3509 xdp := &LinkXdp{} 3510 for _, attr := range attrs { 3511 switch attr.Attr.Type { 3512 case nl.IFLA_XDP_FD: 3513 xdp.Fd = int(native.Uint32(attr.Value[0:4])) 3514 case nl.IFLA_XDP_ATTACHED: 3515 xdp.AttachMode = uint32(attr.Value[0]) 3516 xdp.Attached = xdp.AttachMode != 0 3517 case nl.IFLA_XDP_FLAGS: 3518 xdp.Flags = native.Uint32(attr.Value[0:4]) 3519 case nl.IFLA_XDP_PROG_ID: 3520 xdp.ProgId = native.Uint32(attr.Value[0:4]) 3521 } 3522 } 3523 return xdp, nil 3524 } 3525 3526 func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { 3527 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3528 3529 if iptun.FlowBased { 3530 // In flow based mode, no other attributes need to be configured 3531 data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{}) 3532 return 3533 } 3534 3535 ip := iptun.Local.To4() 3536 if ip != nil { 3537 data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) 3538 } 3539 3540 ip = iptun.Remote.To4() 3541 if ip != nil { 3542 data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) 3543 } 3544 3545 if iptun.Link != 0 { 3546 data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link)) 3547 } 3548 data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc)) 3549 data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl)) 3550 data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos)) 3551 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType)) 3552 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags)) 3553 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport)) 3554 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport)) 3555 data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(iptun.Proto)) 3556 } 3557 3558 func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { 3559 iptun := link.(*Iptun) 3560 for _, datum := range data { 3561 switch datum.Attr.Type { 3562 case nl.IFLA_IPTUN_LOCAL: 3563 iptun.Local = net.IP(datum.Value[0:4]) 3564 case nl.IFLA_IPTUN_REMOTE: 3565 iptun.Remote = net.IP(datum.Value[0:4]) 3566 case nl.IFLA_IPTUN_TTL: 3567 iptun.Ttl = uint8(datum.Value[0]) 3568 case nl.IFLA_IPTUN_TOS: 3569 iptun.Tos = uint8(datum.Value[0]) 3570 case nl.IFLA_IPTUN_PMTUDISC: 3571 iptun.PMtuDisc = uint8(datum.Value[0]) 3572 case nl.IFLA_IPTUN_ENCAP_SPORT: 3573 iptun.EncapSport = ntohs(datum.Value[0:2]) 3574 case nl.IFLA_IPTUN_ENCAP_DPORT: 3575 iptun.EncapDport = ntohs(datum.Value[0:2]) 3576 case nl.IFLA_IPTUN_ENCAP_TYPE: 3577 iptun.EncapType = native.Uint16(datum.Value[0:2]) 3578 case nl.IFLA_IPTUN_ENCAP_FLAGS: 3579 iptun.EncapFlags = native.Uint16(datum.Value[0:2]) 3580 case nl.IFLA_IPTUN_COLLECT_METADATA: 3581 iptun.FlowBased = true 3582 case nl.IFLA_IPTUN_PROTO: 3583 iptun.Proto = datum.Value[0] 3584 } 3585 } 3586 } 3587 3588 func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) { 3589 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3590 3591 if ip6tnl.FlowBased { 3592 // In flow based mode, no other attributes need to be configured 3593 data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{}) 3594 return 3595 } 3596 3597 if ip6tnl.Link != 0 { 3598 data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link)) 3599 } 3600 3601 ip := ip6tnl.Local.To16() 3602 if ip != nil { 3603 data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) 3604 } 3605 3606 ip = ip6tnl.Remote.To16() 3607 if ip != nil { 3608 data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) 3609 } 3610 3611 data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl)) 3612 data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos)) 3613 data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags)) 3614 data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto)) 3615 data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo)) 3616 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit)) 3617 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(ip6tnl.EncapType)) 3618 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(ip6tnl.EncapFlags)) 3619 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(ip6tnl.EncapSport)) 3620 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(ip6tnl.EncapDport)) 3621 } 3622 3623 func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) { 3624 ip6tnl := link.(*Ip6tnl) 3625 for _, datum := range data { 3626 switch datum.Attr.Type { 3627 case nl.IFLA_IPTUN_LOCAL: 3628 ip6tnl.Local = net.IP(datum.Value[:16]) 3629 case nl.IFLA_IPTUN_REMOTE: 3630 ip6tnl.Remote = net.IP(datum.Value[:16]) 3631 case nl.IFLA_IPTUN_TTL: 3632 ip6tnl.Ttl = datum.Value[0] 3633 case nl.IFLA_IPTUN_TOS: 3634 ip6tnl.Tos = datum.Value[0] 3635 case nl.IFLA_IPTUN_FLAGS: 3636 ip6tnl.Flags = native.Uint32(datum.Value[:4]) 3637 case nl.IFLA_IPTUN_PROTO: 3638 ip6tnl.Proto = datum.Value[0] 3639 case nl.IFLA_IPTUN_FLOWINFO: 3640 ip6tnl.FlowInfo = native.Uint32(datum.Value[:4]) 3641 case nl.IFLA_IPTUN_ENCAP_LIMIT: 3642 ip6tnl.EncapLimit = datum.Value[0] 3643 case nl.IFLA_IPTUN_ENCAP_TYPE: 3644 ip6tnl.EncapType = native.Uint16(datum.Value[0:2]) 3645 case nl.IFLA_IPTUN_ENCAP_FLAGS: 3646 ip6tnl.EncapFlags = native.Uint16(datum.Value[0:2]) 3647 case nl.IFLA_IPTUN_ENCAP_SPORT: 3648 ip6tnl.EncapSport = ntohs(datum.Value[0:2]) 3649 case nl.IFLA_IPTUN_ENCAP_DPORT: 3650 ip6tnl.EncapDport = ntohs(datum.Value[0:2]) 3651 case nl.IFLA_IPTUN_COLLECT_METADATA: 3652 ip6tnl.FlowBased = true 3653 } 3654 } 3655 } 3656 3657 func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) { 3658 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3659 3660 if sittun.Link != 0 { 3661 data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link)) 3662 } 3663 3664 ip := sittun.Local.To4() 3665 if ip != nil { 3666 data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) 3667 } 3668 3669 ip = sittun.Remote.To4() 3670 if ip != nil { 3671 data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) 3672 } 3673 3674 if sittun.Ttl > 0 { 3675 // Would otherwise fail on 3.10 kernel 3676 data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl)) 3677 } 3678 3679 data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(sittun.Proto)) 3680 data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos)) 3681 data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc)) 3682 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(sittun.EncapLimit)) 3683 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType)) 3684 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags)) 3685 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport)) 3686 data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport)) 3687 } 3688 3689 func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) { 3690 sittun := link.(*Sittun) 3691 for _, datum := range data { 3692 switch datum.Attr.Type { 3693 case nl.IFLA_IPTUN_LOCAL: 3694 sittun.Local = net.IP(datum.Value[0:4]) 3695 case nl.IFLA_IPTUN_REMOTE: 3696 sittun.Remote = net.IP(datum.Value[0:4]) 3697 case nl.IFLA_IPTUN_TTL: 3698 sittun.Ttl = datum.Value[0] 3699 case nl.IFLA_IPTUN_TOS: 3700 sittun.Tos = datum.Value[0] 3701 case nl.IFLA_IPTUN_PMTUDISC: 3702 sittun.PMtuDisc = datum.Value[0] 3703 case nl.IFLA_IPTUN_PROTO: 3704 sittun.Proto = datum.Value[0] 3705 case nl.IFLA_IPTUN_ENCAP_TYPE: 3706 sittun.EncapType = native.Uint16(datum.Value[0:2]) 3707 case nl.IFLA_IPTUN_ENCAP_FLAGS: 3708 sittun.EncapFlags = native.Uint16(datum.Value[0:2]) 3709 case nl.IFLA_IPTUN_ENCAP_SPORT: 3710 sittun.EncapSport = ntohs(datum.Value[0:2]) 3711 case nl.IFLA_IPTUN_ENCAP_DPORT: 3712 sittun.EncapDport = ntohs(datum.Value[0:2]) 3713 } 3714 } 3715 } 3716 3717 func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) { 3718 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3719 3720 family := FAMILY_V4 3721 if vti.Local.To4() == nil { 3722 family = FAMILY_V6 3723 } 3724 3725 var ip net.IP 3726 3727 if family == FAMILY_V4 { 3728 ip = vti.Local.To4() 3729 } else { 3730 ip = vti.Local 3731 } 3732 if ip != nil { 3733 data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip)) 3734 } 3735 3736 if family == FAMILY_V4 { 3737 ip = vti.Remote.To4() 3738 } else { 3739 ip = vti.Remote 3740 } 3741 if ip != nil { 3742 data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip)) 3743 } 3744 3745 if vti.Link != 0 { 3746 data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link)) 3747 } 3748 3749 data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey)) 3750 data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey)) 3751 } 3752 3753 func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) { 3754 vti := link.(*Vti) 3755 for _, datum := range data { 3756 switch datum.Attr.Type { 3757 case nl.IFLA_VTI_LOCAL: 3758 vti.Local = net.IP(datum.Value) 3759 case nl.IFLA_VTI_REMOTE: 3760 vti.Remote = net.IP(datum.Value) 3761 case nl.IFLA_VTI_IKEY: 3762 vti.IKey = ntohl(datum.Value[0:4]) 3763 case nl.IFLA_VTI_OKEY: 3764 vti.OKey = ntohl(datum.Value[0:4]) 3765 } 3766 } 3767 } 3768 3769 func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) { 3770 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3771 b := make([]byte, 4) 3772 native.PutUint32(b, uint32(vrf.Table)) 3773 data.AddRtAttr(nl.IFLA_VRF_TABLE, b) 3774 } 3775 3776 func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) { 3777 vrf := link.(*Vrf) 3778 for _, datum := range data { 3779 switch datum.Attr.Type { 3780 case nl.IFLA_VRF_TABLE: 3781 vrf.Table = native.Uint32(datum.Value[0:4]) 3782 } 3783 } 3784 } 3785 3786 func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) { 3787 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3788 if bridge.MulticastSnooping != nil { 3789 data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping)) 3790 } 3791 if bridge.AgeingTime != nil { 3792 data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(*bridge.AgeingTime)) 3793 } 3794 if bridge.HelloTime != nil { 3795 data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime)) 3796 } 3797 if bridge.VlanFiltering != nil { 3798 data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering)) 3799 } 3800 if bridge.VlanDefaultPVID != nil { 3801 data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID)) 3802 } 3803 if bridge.GroupFwdMask != nil { 3804 data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask)) 3805 } 3806 } 3807 3808 func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { 3809 br := bridge.(*Bridge) 3810 for _, datum := range data { 3811 switch datum.Attr.Type { 3812 case nl.IFLA_BR_AGEING_TIME: 3813 ageingTime := native.Uint32(datum.Value[0:4]) 3814 br.AgeingTime = &ageingTime 3815 case nl.IFLA_BR_HELLO_TIME: 3816 helloTime := native.Uint32(datum.Value[0:4]) 3817 br.HelloTime = &helloTime 3818 case nl.IFLA_BR_MCAST_SNOOPING: 3819 mcastSnooping := datum.Value[0] == 1 3820 br.MulticastSnooping = &mcastSnooping 3821 case nl.IFLA_BR_VLAN_FILTERING: 3822 vlanFiltering := datum.Value[0] == 1 3823 br.VlanFiltering = &vlanFiltering 3824 case nl.IFLA_BR_VLAN_DEFAULT_PVID: 3825 vlanDefaultPVID := native.Uint16(datum.Value[0:2]) 3826 br.VlanDefaultPVID = &vlanDefaultPVID 3827 case nl.IFLA_BR_GROUP_FWD_MASK: 3828 mask := native.Uint16(datum.Value[0:2]) 3829 br.GroupFwdMask = &mask 3830 } 3831 } 3832 } 3833 3834 func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) { 3835 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3836 data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0))) 3837 data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1))) 3838 data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072)) 3839 if gtp.Role != nl.GTP_ROLE_GGSN { 3840 data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role))) 3841 } 3842 } 3843 3844 func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) { 3845 gtp := link.(*GTP) 3846 for _, datum := range data { 3847 switch datum.Attr.Type { 3848 case nl.IFLA_GTP_FD0: 3849 gtp.FD0 = int(native.Uint32(datum.Value)) 3850 case nl.IFLA_GTP_FD1: 3851 gtp.FD1 = int(native.Uint32(datum.Value)) 3852 case nl.IFLA_GTP_PDP_HASHSIZE: 3853 gtp.PDPHashsize = int(native.Uint32(datum.Value)) 3854 case nl.IFLA_GTP_ROLE: 3855 gtp.Role = int(native.Uint32(datum.Value)) 3856 } 3857 } 3858 } 3859 3860 func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) { 3861 var vfs []VfInfo 3862 3863 for i, element := range data { 3864 if element.Attr.Type != nl.IFLA_VF_INFO { 3865 return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type) 3866 } 3867 vfAttrs, err := nl.ParseRouteAttr(element.Value) 3868 if err != nil { 3869 return nil, err 3870 } 3871 3872 vf, err := parseVfInfo(vfAttrs, i) 3873 if err != nil { 3874 return nil, err 3875 } 3876 vfs = append(vfs, vf) 3877 } 3878 return vfs, nil 3879 } 3880 3881 func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) { 3882 vf := VfInfo{ID: id} 3883 for _, element := range data { 3884 switch element.Attr.Type { 3885 case nl.IFLA_VF_MAC: 3886 mac := nl.DeserializeVfMac(element.Value[:]) 3887 vf.Mac = mac.Mac[:6] 3888 case nl.IFLA_VF_VLAN: 3889 vl := nl.DeserializeVfVlan(element.Value[:]) 3890 vf.Vlan = int(vl.Vlan) 3891 vf.Qos = int(vl.Qos) 3892 case nl.IFLA_VF_VLAN_LIST: 3893 vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:]) 3894 if err != nil { 3895 return vf, err 3896 } 3897 vf.VlanProto = int(vfVlanInfoList[0].VlanProto) 3898 case nl.IFLA_VF_TX_RATE: 3899 txr := nl.DeserializeVfTxRate(element.Value[:]) 3900 vf.TxRate = int(txr.Rate) 3901 case nl.IFLA_VF_SPOOFCHK: 3902 sp := nl.DeserializeVfSpoofchk(element.Value[:]) 3903 vf.Spoofchk = sp.Setting != 0 3904 case nl.IFLA_VF_LINK_STATE: 3905 ls := nl.DeserializeVfLinkState(element.Value[:]) 3906 vf.LinkState = ls.LinkState 3907 case nl.IFLA_VF_RATE: 3908 vfr := nl.DeserializeVfRate(element.Value[:]) 3909 vf.MaxTxRate = vfr.MaxTxRate 3910 vf.MinTxRate = vfr.MinTxRate 3911 case nl.IFLA_VF_STATS: 3912 vfstats := nl.DeserializeVfStats(element.Value[:]) 3913 vf.RxPackets = vfstats.RxPackets 3914 vf.TxPackets = vfstats.TxPackets 3915 vf.RxBytes = vfstats.RxBytes 3916 vf.TxBytes = vfstats.TxBytes 3917 vf.Multicast = vfstats.Multicast 3918 vf.Broadcast = vfstats.Broadcast 3919 vf.RxDropped = vfstats.RxDropped 3920 vf.TxDropped = vfstats.TxDropped 3921 3922 case nl.IFLA_VF_RSS_QUERY_EN: 3923 result := nl.DeserializeVfRssQueryEn(element.Value) 3924 vf.RssQuery = result.Setting 3925 3926 case nl.IFLA_VF_TRUST: 3927 result := nl.DeserializeVfTrust(element.Value) 3928 vf.Trust = result.Setting 3929 } 3930 } 3931 return vf, nil 3932 } 3933 3934 func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) { 3935 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 3936 data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex))) 3937 if xfrmi.Ifid != 0 { 3938 data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid)) 3939 } 3940 } 3941 3942 func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) { 3943 xfrmi := link.(*Xfrmi) 3944 for _, datum := range data { 3945 switch datum.Attr.Type { 3946 case nl.IFLA_XFRM_LINK: 3947 xfrmi.ParentIndex = int(native.Uint32(datum.Value)) 3948 case nl.IFLA_XFRM_IF_ID: 3949 xfrmi.Ifid = native.Uint32(datum.Value) 3950 } 3951 } 3952 } 3953 3954 func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error { 3955 fd, err := getSocketUDP() 3956 if err != nil { 3957 return err 3958 } 3959 defer syscall.Close(fd) 3960 3961 ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name) 3962 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq))) 3963 if errno != 0 { 3964 return fmt.Errorf("errno=%v", errno) 3965 } 3966 return nil 3967 } 3968 3969 // LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface. 3970 // 3971 // Multiple calls keeps the status unchanged(shown in the unit test). 3972 func LinkSetBondSlaveActive(link Link, master *Bond) error { 3973 err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master) 3974 if err != nil { 3975 return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err) 3976 } 3977 return nil 3978 } 3979 3980 // LinkSetBondSlave add slave to bond link via ioctl interface. 3981 func LinkSetBondSlave(link Link, master *Bond) error { 3982 err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master) 3983 if err != nil { 3984 return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err) 3985 } 3986 return nil 3987 } 3988 3989 // LinkSetBondSlave removes specified slave from bond link via ioctl interface. 3990 func LinkDelBondSlave(link Link, master *Bond) error { 3991 err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master) 3992 if err != nil { 3993 return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err) 3994 } 3995 return nil 3996 } 3997 3998 // LinkSetBondSlaveQueueId modify bond slave queue-id. 3999 func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error { 4000 base := link.Attrs() 4001 h.ensureIndex(base) 4002 req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) 4003 4004 msg := nl.NewIfInfomsg(unix.AF_UNSPEC) 4005 msg.Index = int32(base.Index) 4006 req.AddData(msg) 4007 4008 linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) 4009 data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) 4010 data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId)) 4011 4012 req.AddData(linkInfo) 4013 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 4014 return err 4015 } 4016 4017 // LinkSetBondSlaveQueueId modify bond slave queue-id. 4018 func LinkSetBondSlaveQueueId(link Link, queueId uint16) error { 4019 return pkgHandle.LinkSetBondSlaveQueueId(link, queueId) 4020 } 4021 4022 func vethStatsSerialize(stats ethtoolStats) ([]byte, error) { 4023 statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0))) 4024 b := make([]byte, 0, statsSize) 4025 buf := bytes.NewBuffer(b) 4026 err := binary.Write(buf, nl.NativeEndian(), stats) 4027 return buf.Bytes()[:statsSize], err 4028 } 4029 4030 type vethEthtoolStats struct { 4031 Cmd uint32 4032 NStats uint32 4033 Peer uint64 4034 // Newer kernels have XDP stats in here, but we only care 4035 // to extract the peer ifindex here. 4036 } 4037 4038 func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) { 4039 var stats = vethEthtoolStats{} 4040 err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats) 4041 return stats, err 4042 } 4043 4044 // VethPeerIndex get veth peer index. 4045 func VethPeerIndex(link *Veth) (int, error) { 4046 fd, err := getSocketUDP() 4047 if err != nil { 4048 return -1, err 4049 } 4050 defer syscall.Close(fd) 4051 4052 ifreq, sSet := newIocltStringSetReq(link.Name) 4053 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) 4054 if errno != 0 { 4055 return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) 4056 } 4057 4058 stats := ethtoolStats{ 4059 cmd: ETHTOOL_GSTATS, 4060 nStats: sSet.data[0], 4061 } 4062 4063 buffer, err := vethStatsSerialize(stats) 4064 if err != nil { 4065 return -1, err 4066 } 4067 4068 ifreq.Data = uintptr(unsafe.Pointer(&buffer[0])) 4069 _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) 4070 if errno != 0 { 4071 return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) 4072 } 4073 4074 vstats, err := vethStatsDeserialize(buffer) 4075 if err != nil { 4076 return -1, err 4077 } 4078 4079 return int(vstats.Peer), nil 4080 } 4081 4082 func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) { 4083 tuntap := link.(*Tuntap) 4084 for _, datum := range data { 4085 switch datum.Attr.Type { 4086 case nl.IFLA_TUN_OWNER: 4087 tuntap.Owner = native.Uint32(datum.Value) 4088 case nl.IFLA_TUN_GROUP: 4089 tuntap.Group = native.Uint32(datum.Value) 4090 case nl.IFLA_TUN_TYPE: 4091 tuntap.Mode = TuntapMode(uint8(datum.Value[0])) 4092 case nl.IFLA_TUN_PI: 4093 if datum.Value[0] == 0 { 4094 tuntap.Flags |= TUNTAP_NO_PI 4095 } 4096 case nl.IFLA_TUN_VNET_HDR: 4097 if datum.Value[0] == 1 { 4098 tuntap.Flags |= TUNTAP_VNET_HDR 4099 } 4100 case nl.IFLA_TUN_PERSIST: 4101 tuntap.NonPersist = false 4102 if uint8(datum.Value[0]) == 0 { 4103 tuntap.NonPersist = true 4104 } 4105 case nl.IFLA_TUN_MULTI_QUEUE: 4106 if datum.Value[0] == 1 { 4107 tuntap.Flags |= TUNTAP_MULTI_QUEUE 4108 } 4109 case nl.IFLA_TUN_NUM_QUEUES: 4110 tuntap.Queues = int(native.Uint32(datum.Value)) 4111 case nl.IFLA_TUN_NUM_DISABLED_QUEUES: 4112 tuntap.DisabledQueues = int(native.Uint32(datum.Value)) 4113 } 4114 } 4115 } 4116 4117 func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) { 4118 ipoib := link.(*IPoIB) 4119 for _, datum := range data { 4120 switch datum.Attr.Type { 4121 case nl.IFLA_IPOIB_PKEY: 4122 ipoib.Pkey = uint16(native.Uint16(datum.Value)) 4123 case nl.IFLA_IPOIB_MODE: 4124 ipoib.Mode = IPoIBMode(native.Uint16(datum.Value)) 4125 case nl.IFLA_IPOIB_UMCAST: 4126 ipoib.Umcast = uint16(native.Uint16(datum.Value)) 4127 } 4128 } 4129 } 4130 4131 func parseCanData(link Link, data []syscall.NetlinkRouteAttr) { 4132 can := link.(*Can) 4133 for _, datum := range data { 4134 4135 switch datum.Attr.Type { 4136 case nl.IFLA_CAN_BITTIMING: 4137 can.BitRate = native.Uint32(datum.Value) 4138 can.SamplePoint = native.Uint32(datum.Value[4:]) 4139 can.TimeQuanta = native.Uint32(datum.Value[8:]) 4140 can.PropagationSegment = native.Uint32(datum.Value[12:]) 4141 can.PhaseSegment1 = native.Uint32(datum.Value[16:]) 4142 can.PhaseSegment2 = native.Uint32(datum.Value[20:]) 4143 can.SyncJumpWidth = native.Uint32(datum.Value[24:]) 4144 can.BitRatePreScaler = native.Uint32(datum.Value[28:]) 4145 case nl.IFLA_CAN_BITTIMING_CONST: 4146 can.Name = string(datum.Value[:16]) 4147 can.TimeSegment1Min = native.Uint32(datum.Value[16:]) 4148 can.TimeSegment1Max = native.Uint32(datum.Value[20:]) 4149 can.TimeSegment2Min = native.Uint32(datum.Value[24:]) 4150 can.TimeSegment2Max = native.Uint32(datum.Value[28:]) 4151 can.SyncJumpWidthMax = native.Uint32(datum.Value[32:]) 4152 can.BitRatePreScalerMin = native.Uint32(datum.Value[36:]) 4153 can.BitRatePreScalerMax = native.Uint32(datum.Value[40:]) 4154 can.BitRatePreScalerInc = native.Uint32(datum.Value[44:]) 4155 case nl.IFLA_CAN_CLOCK: 4156 can.ClockFrequency = native.Uint32(datum.Value) 4157 case nl.IFLA_CAN_STATE: 4158 can.State = native.Uint32(datum.Value) 4159 case nl.IFLA_CAN_CTRLMODE: 4160 can.Mask = native.Uint32(datum.Value) 4161 can.Flags = native.Uint32(datum.Value[4:]) 4162 case nl.IFLA_CAN_BERR_COUNTER: 4163 can.TxError = native.Uint16(datum.Value) 4164 can.RxError = native.Uint16(datum.Value[2:]) 4165 case nl.IFLA_CAN_RESTART_MS: 4166 can.RestartMs = native.Uint32(datum.Value) 4167 case nl.IFLA_CAN_DATA_BITTIMING_CONST: 4168 case nl.IFLA_CAN_RESTART: 4169 case nl.IFLA_CAN_DATA_BITTIMING: 4170 case nl.IFLA_CAN_TERMINATION: 4171 case nl.IFLA_CAN_TERMINATION_CONST: 4172 case nl.IFLA_CAN_BITRATE_CONST: 4173 case nl.IFLA_CAN_DATA_BITRATE_CONST: 4174 case nl.IFLA_CAN_BITRATE_MAX: 4175 } 4176 } 4177 } 4178 4179 func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) { 4180 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 4181 data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey))) 4182 data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode))) 4183 data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast))) 4184 } 4185 4186 func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) { 4187 data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) 4188 4189 data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port))) 4190 data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType))) 4191 if bareudp.SrcPortMin != 0 { 4192 data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin)) 4193 } 4194 if bareudp.MultiProto { 4195 data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{}) 4196 } 4197 } 4198 4199 func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) { 4200 bareudp := link.(*BareUDP) 4201 for _, attr := range data { 4202 switch attr.Attr.Type { 4203 case nl.IFLA_BAREUDP_PORT: 4204 bareudp.Port = binary.BigEndian.Uint16(attr.Value) 4205 case nl.IFLA_BAREUDP_ETHERTYPE: 4206 bareudp.EtherType = binary.BigEndian.Uint16(attr.Value) 4207 case nl.IFLA_BAREUDP_SRCPORT_MIN: 4208 bareudp.SrcPortMin = native.Uint16(attr.Value) 4209 case nl.IFLA_BAREUDP_MULTIPROTO_MODE: 4210 bareudp.MultiProto = true 4211 } 4212 } 4213 }