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