Skip to content

Commit 7f792e6

Browse files
authored
Merge pull request #1990 from gwenya/netlink
Use netlink instead of calling iproute2 commands
2 parents b4db2a1 + b9fcc87 commit 7f792e6

29 files changed

+1262
-1148
lines changed

cmd/incusd/main_forknet.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,13 @@ func (c *cmdForknet) dhcpRunV4(errorChannel chan error, iface string, hostname s
413413
}
414414

415415
// Network configuration.
416-
netMask, _ := lease.Offer.SubnetMask().Size()
417-
418416
addr := &ip.Addr{
419417
DevName: iface,
420-
Address: fmt.Sprintf("%s/%d", lease.Offer.YourIPAddr, netMask),
421-
Family: ip.FamilyV4,
418+
Address: &net.IPNet{
419+
IP: lease.Offer.YourIPAddr,
420+
Mask: lease.Offer.SubnetMask(),
421+
},
422+
Family: ip.FamilyV4,
422423
}
423424

424425
err = addr.Add()
@@ -432,12 +433,12 @@ func (c *cmdForknet) dhcpRunV4(errorChannel chan error, iface string, hostname s
432433
for _, staticRoute := range lease.Offer.ClasslessStaticRoute() {
433434
route := &ip.Route{
434435
DevName: iface,
435-
Route: staticRoute.Dest.String(),
436+
Route: staticRoute.Dest,
436437
Family: ip.FamilyV4,
437438
}
438439

439440
if !staticRoute.Router.IsUnspecified() {
440-
route.Via = staticRoute.Router.String()
441+
route.Via = staticRoute.Router
441442
}
442443

443444
err = route.Add()
@@ -450,8 +451,8 @@ func (c *cmdForknet) dhcpRunV4(errorChannel chan error, iface string, hostname s
450451
} else {
451452
route := &ip.Route{
452453
DevName: iface,
453-
Route: "default",
454-
Via: lease.Offer.Router()[0].String(),
454+
Route: nil,
455+
Via: lease.Offer.Router()[0],
455456
Family: ip.FamilyV4,
456457
}
457458

@@ -575,8 +576,11 @@ func (c *cmdForknet) dhcpRunV6(errorChannel chan error, iface string, hostname s
575576
for _, iaaddr := range ia.Options.Addresses() {
576577
addr := &ip.Addr{
577578
DevName: iface,
578-
Address: fmt.Sprintf("%s/64", iaaddr.IPv6Addr),
579-
Family: ip.FamilyV6,
579+
Address: &net.IPNet{
580+
IP: iaaddr.IPv6Addr,
581+
Mask: net.CIDRMask(64, 128),
582+
},
583+
Family: ip.FamilyV6,
580584
}
581585

582586
err = addr.Add()

internal/server/device/device_utils_network.go

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/mdlayher/arp"
1717
"github.com/mdlayher/ndp"
18+
"golang.org/x/sys/unix"
1819

1920
deviceConfig "github.com/lxc/incus/v6/internal/server/device/config"
2021
pcidev "github.com/lxc/incus/v6/internal/server/device/pci"
@@ -216,13 +217,13 @@ func networkCreateVethPair(hostName string, m deviceConfig.Device) (string, uint
216217

217218
veth := &ip.Veth{
218219
Link: ip.Link{
219-
Name: hostName,
220-
Up: true,
220+
Name: hostName,
221+
Up: true,
222+
Master: m["vrf"],
221223
},
222224
Peer: ip.Link{
223225
Name: network.RandomDevName("veth"),
224226
},
225-
Master: m["vrf"],
226227
}
227228

228229
// Set the MTU on both ends.
@@ -412,20 +413,20 @@ func networkNICRouteAdd(routeDev string, routes ...string) error {
412413

413414
for _, r := range routes {
414415
route := r // Local var for revert.
415-
ipAddress, _, err := net.ParseCIDR(route)
416+
ipNet, err := ip.ParseIPNet(route)
416417
if err != nil {
417418
return fmt.Errorf("Invalid route %q: %w", route, err)
418419
}
419420

420421
ipVersion := ip.FamilyV4
421-
if ipAddress.To4() == nil {
422+
if ipNet.IP.To4() == nil {
422423
ipVersion = ip.FamilyV6
423424
}
424425

425426
// Add IP route (using boot proto to avoid conflicts with network defined static routes).
426427
r := &ip.Route{
427428
DevName: routeDev,
428-
Route: route,
429+
Route: ipNet,
429430
Proto: "boot",
430431
Family: ipVersion,
431432
}
@@ -438,7 +439,7 @@ func networkNICRouteAdd(routeDev string, routes ...string) error {
438439
reverter.Add(func() {
439440
r := &ip.Route{
440441
DevName: routeDev,
441-
Route: route,
442+
Route: ipNet,
442443
Proto: "boot",
443444
Family: ipVersion,
444445
}
@@ -466,21 +467,21 @@ func networkNICRouteDelete(routeDev string, routes ...string) {
466467

467468
for _, r := range routes {
468469
route := r // Local var for revert.
469-
ipAddress, _, err := net.ParseCIDR(route)
470+
ipNet, err := ip.ParseIPNet(route)
470471
if err != nil {
471472
logger.Errorf("Failed to remove static route %q to %q: %v", route, routeDev, err)
472473
continue
473474
}
474475

475476
ipVersion := ip.FamilyV4
476-
if ipAddress.To4() == nil {
477+
if ipNet.IP.To4() == nil {
477478
ipVersion = ip.FamilyV6
478479
}
479480

480481
// Add IP route (using boot proto to avoid conflicts with network defined static routes).
481482
r := &ip.Route{
482483
DevName: routeDev,
483-
Route: route,
484+
Route: ipNet,
484485
Proto: "boot",
485486
Family: ipVersion,
486487
}
@@ -527,14 +528,21 @@ func networkSetupHostVethLimits(d *deviceCommon, oldConfig deviceConfig.Device,
527528
}
528529

529530
// Clean any existing entry
530-
qdisc := &ip.Qdisc{Dev: veth, Root: true}
531-
_ = qdisc.Delete()
532-
qdisc = &ip.Qdisc{Dev: veth, Ingress: true}
533-
_ = qdisc.Delete()
531+
qdiscIngress := &ip.QdiscIngress{Qdisc: ip.Qdisc{Dev: veth, Handle: "ffff:0"}}
532+
err = qdiscIngress.Delete()
533+
if err != nil && !errors.Is(err, unix.ENOENT) {
534+
return err
535+
}
536+
537+
qdiscHTB := &ip.QdiscHTB{Qdisc: ip.Qdisc{Dev: veth, Handle: "1:0", Parent: "root"}}
538+
err = qdiscHTB.Delete()
539+
if err != nil && !errors.Is(err, unix.ENOENT) {
540+
return err
541+
}
534542

535543
// Apply new limits
536544
if d.config["limits.ingress"] != "" {
537-
qdiscHTB := &ip.QdiscHTB{Qdisc: ip.Qdisc{Dev: veth, Handle: "1:0", Root: true}, Default: "10"}
545+
qdiscHTB = &ip.QdiscHTB{Qdisc: ip.Qdisc{Dev: veth, Handle: "1:0", Parent: "root"}, Default: 10}
538546
err := qdiscHTB.Add()
539547
if err != nil {
540548
return fmt.Errorf("Failed to create root tc qdisc: %s", err)
@@ -546,22 +554,22 @@ func networkSetupHostVethLimits(d *deviceCommon, oldConfig deviceConfig.Device,
546554
return fmt.Errorf("Failed to create limit tc class: %s", err)
547555
}
548556

549-
filter := &ip.U32Filter{Filter: ip.Filter{Dev: veth, Parent: "1:0", Protocol: "all", Flowid: "1:1"}, Value: "0", Mask: "0"}
557+
filter := &ip.U32Filter{Filter: ip.Filter{Dev: veth, Parent: "1:0", Protocol: "all", Flowid: "1:1"}, Value: 0, Mask: 0}
550558
err = filter.Add()
551559
if err != nil {
552560
return fmt.Errorf("Failed to create tc filter: %s", err)
553561
}
554562
}
555563

556564
if d.config["limits.egress"] != "" {
557-
qdisc = &ip.Qdisc{Dev: veth, Handle: "ffff:0", Ingress: true}
558-
err := qdisc.Add()
565+
qdiscIngress = &ip.QdiscIngress{Qdisc: ip.Qdisc{Dev: veth, Handle: "ffff:0"}}
566+
err := qdiscIngress.Add()
559567
if err != nil {
560568
return fmt.Errorf("Failed to create ingress tc qdisc: %s", err)
561569
}
562570

563-
police := &ip.ActionPolice{Rate: fmt.Sprintf("%dbit", egressInt), Burst: fmt.Sprintf("%d", egressInt/40), Mtu: "64kb", Drop: true}
564-
filter := &ip.U32Filter{Filter: ip.Filter{Dev: veth, Parent: "ffff:0", Protocol: "all"}, Value: "0", Mask: "0", Actions: []ip.Action{police}}
571+
police := &ip.ActionPolice{Rate: uint32(egressInt / 8), Burst: uint32(egressInt / 40), Mtu: 65535, Drop: true}
572+
filter := &ip.U32Filter{Filter: ip.Filter{Dev: veth, Parent: "ffff:0", Protocol: "all"}, Value: 0, Mask: 0, Actions: []ip.Action{police}}
565573
err = filter.Add()
566574
if err != nil {
567575
return fmt.Errorf("Failed to create ingress tc filter: %s", err)
@@ -690,7 +698,7 @@ func bgpRemovePrefix(d *deviceCommon, config map[string]string) error {
690698
return nil
691699
}
692700

693-
// networkSRIOVParentVFInfo returns info about an SR-IOV virtual function from the parent NIC using the ip tool.
701+
// networkSRIOVParentVFInfo returns info about an SR-IOV virtual function from the parent NIC.
694702
func networkSRIOVParentVFInfo(vfParent string, vfID int) (ip.VirtFuncInfo, error) {
695703
link := &ip.Link{Name: vfParent}
696704
vfi, err := link.GetVFInfo(vfID)
@@ -716,9 +724,9 @@ func networkSRIOVSetupVF(d deviceCommon, vfParent string, vfDevice string, vfID
716724

717725
// Record properties of VF settings on the parent device.
718726
volatile["last_state.vf.parent"] = vfParent
719-
volatile["last_state.vf.hwaddr"] = vfInfo.Address
727+
volatile["last_state.vf.hwaddr"] = vfInfo.Address.String()
720728
volatile["last_state.vf.id"] = fmt.Sprintf("%d", vfID)
721-
volatile["last_state.vf.vlan"] = fmt.Sprintf("%d", vfInfo.VLANs[0]["vlan"])
729+
volatile["last_state.vf.vlan"] = fmt.Sprintf("%d", vfInfo.VLAN)
722730
volatile["last_state.vf.spoofcheck"] = fmt.Sprintf("%t", vfInfo.SpoofCheck)
723731

724732
// Record the host interface we represents the VF device which we will move into instance.
@@ -772,7 +780,7 @@ func networkSRIOVSetupVF(d deviceCommon, vfParent string, vfDevice string, vfID
772780
}
773781

774782
// Now that MAC is set on VF, we can enable spoof checking.
775-
err = link.SetVfSpoofchk(volatile["last_state.vf.id"], "on")
783+
err = link.SetVfSpoofchk(volatile["last_state.vf.id"], true)
776784
if err != nil {
777785
return vfPCIDev, 0, fmt.Errorf("Failed enabling spoof check for VF %q: %w", volatile["last_state.vf.id"], err)
778786
}
@@ -784,7 +792,7 @@ func networkSRIOVSetupVF(d deviceCommon, vfParent string, vfDevice string, vfID
784792
_ = link.SetVfAddress(volatile["last_state.vf.id"], "00:00:00:00:00:00")
785793

786794
// Ensure spoof checking is disabled if not enabled in instance (only for real VF).
787-
err = link.SetVfSpoofchk(volatile["last_state.vf.id"], "off")
795+
err = link.SetVfSpoofchk(volatile["last_state.vf.id"], false)
788796
if err != nil && d.config["security.mac_filtering"] != "" {
789797
return vfPCIDev, 0, fmt.Errorf("Failed disabling spoof check for VF %q: %w", volatile["last_state.vf.id"], err)
790798
}
@@ -897,11 +905,7 @@ func networkSRIOVRestoreVF(d deviceCommon, useSpoofCheck bool, volatile map[stri
897905
// Reset VF MAC spoofing protection if recorded. Do this first before resetting the MAC
898906
// to avoid any issues with zero MACs refusing to be set whilst spoof check is on.
899907
if volatile["last_state.vf.spoofcheck"] != "" {
900-
mode := "off"
901-
if util.IsTrue(volatile["last_state.vf.spoofcheck"]) {
902-
mode = "on"
903-
}
904-
908+
mode := util.IsTrue(volatile["last_state.vf.spoofcheck"])
905909
link := &ip.Link{Name: parent}
906910
err := link.SetVfSpoofchk(volatile["last_state.vf.id"], mode)
907911
if err != nil && d.config["security.mac_filtering"] != "" {

internal/server/device/nic_bridged.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,22 +2001,22 @@ func (d *nicBridged) State() (*api.InstanceStateNetwork, error) {
20012001
// Get IP addresses from IP neighbour cache if present.
20022002
neighIPs, err := network.GetNeighbourIPs(d.config["parent"], hwAddr)
20032003
if err == nil {
2004-
validStates := []string{
2005-
string(ip.NeighbourIPStatePermanent),
2006-
string(ip.NeighbourIPStateNoARP),
2007-
string(ip.NeighbourIPStateReachable),
2004+
validStates := []ip.NeighbourIPState{
2005+
ip.NeighbourIPStatePermanent,
2006+
ip.NeighbourIPStateNoARP,
2007+
ip.NeighbourIPStateReachable,
20082008
}
20092009

20102010
// Add any valid-state neighbour IP entries first.
20112011
for _, neighIP := range neighIPs {
2012-
if slices.Contains(validStates, string(neighIP.State)) {
2012+
if slices.Contains(validStates, neighIP.State) {
20132013
ipStore(neighIP.Addr)
20142014
}
20152015
}
20162016

20172017
// Add any non-failed-state entries.
20182018
for _, neighIP := range neighIPs {
2019-
if neighIP.State != ip.NeighbourIPStateFailed && !slices.Contains(validStates, string(neighIP.State)) {
2019+
if neighIP.State != ip.NeighbourIPStateFailed && !slices.Contains(validStates, neighIP.State) {
20202020
ipStore(neighIP.Addr)
20212021
}
20222022
}

internal/server/device/nic_ipvlan.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,13 @@ func (d *nicIPVLAN) Start() (*deviceConfig.RunConfig, error) {
365365

366366
// Perform network configuration.
367367
for _, keyPrefix := range []string{"ipv4", "ipv6"} {
368-
var ipFamilyArg string
368+
var ipFamily ip.Family
369369

370370
switch keyPrefix {
371371
case "ipv4":
372-
ipFamilyArg = ip.FamilyV4
372+
ipFamily = ip.FamilyV4
373373
case "ipv6":
374-
ipFamilyArg = ip.FamilyV6
374+
ipFamily = ip.FamilyV6
375375
}
376376

377377
addresses := util.SplitNTrimSpace(d.config[fmt.Sprintf("%s.address", keyPrefix)], ",", -1, true)
@@ -393,9 +393,9 @@ func (d *nicIPVLAN) Start() (*deviceConfig.RunConfig, error) {
393393
// Apply host-side static routes to main routing table to allow neighbour proxy.
394394
r := ip.Route{
395395
DevName: "lo",
396-
Route: addr.String(),
396+
Route: addr,
397397
Table: "main",
398-
Family: ipFamilyArg,
398+
Family: ipFamily,
399399
}
400400

401401
err = r.Add()
@@ -410,9 +410,9 @@ func (d *nicIPVLAN) Start() (*deviceConfig.RunConfig, error) {
410410
if d.config[hostTableKey] != "" {
411411
r := &ip.Route{
412412
DevName: "lo",
413-
Route: addr.String(),
413+
Route: addr,
414414
Table: d.config[hostTableKey],
415-
Family: ipFamilyArg,
415+
Family: ipFamily,
416416
}
417417

418418
err := r.Add()
@@ -540,13 +540,13 @@ func (d *nicIPVLAN) postStop() error {
540540

541541
// Clean up host-side network configuration.
542542
for _, keyPrefix := range []string{"ipv4", "ipv6"} {
543-
var ipFamilyArg string
543+
var ipFamily ip.Family
544544

545545
switch keyPrefix {
546546
case "ipv4":
547-
ipFamilyArg = ip.FamilyV4
547+
ipFamily = ip.FamilyV4
548548
case "ipv6":
549-
ipFamilyArg = ip.FamilyV6
549+
ipFamily = ip.FamilyV6
550550
}
551551

552552
addresses := util.SplitNTrimSpace(d.config[fmt.Sprintf("%s.address", keyPrefix)], ",", -1, true)
@@ -563,9 +563,9 @@ func (d *nicIPVLAN) postStop() error {
563563
if mode == ipvlanModeL3S {
564564
r := ip.Route{
565565
DevName: "lo",
566-
Route: addr.String(),
566+
Route: addr,
567567
Table: "main",
568-
Family: ipFamilyArg,
568+
Family: ipFamily,
569569
}
570570

571571
err := r.Delete()
@@ -588,9 +588,9 @@ func (d *nicIPVLAN) postStop() error {
588588
if d.config[hostTableKey] != "" {
589589
r := &ip.Route{
590590
DevName: "lo",
591-
Route: addr.String(),
591+
Route: addr,
592592
Table: d.config[hostTableKey],
593-
Family: ipFamilyArg,
593+
Family: ipFamily,
594594
}
595595

596596
err := r.Delete()

0 commit comments

Comments
 (0)