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