Skip to content
This repository has been archived by the owner on Aug 26, 2024. It is now read-only.

Detaching program hangs when using SKB mode #28

Open
Crosse opened this issue Jan 4, 2023 · 0 comments
Open

Detaching program hangs when using SKB mode #28

Crosse opened this issue Jan 4, 2023 · 0 comments

Comments

@Crosse
Copy link

Crosse commented Jan 4, 2023

Hi!

I've noticed that when I explicitly set XDP_FLAGS_SKB_MODE in xdp.DefaultXdpFlags, removing a program from an interface never completes. I've tracked the issue down to here:

xdp/program.go

Lines 257 to 259 in 56d7123

if err = netlink.LinkSetXdpFd(link, -1); err != nil {
return fmt.Errorf("netlink.LinkSetXdpFd(link, -1) failed: %v", err)
}

If I change the call from netlink.LinkSetXdpFd() to netlink.LinkSetXdpFdWithFlags() and pass in xdp.DefaultXdpFlags, then the detach works:

@@ -254,8 +254,8 @@ func removeProgram(Ifindex int) error {
        if !isXdpAttached(link) {
                return nil
        }
-       if err = netlink.LinkSetXdpFd(link, -1); err != nil {
-               return fmt.Errorf("netlink.LinkSetXdpFd(link, -1) failed: %v", err)
+       if err = netlink.LinkSetXdpFdWithFlags(link, -1, int(DefaultXdpFlags)); err != nil {
+               return fmt.Errorf("netlink.LinkSetXdpFdWithFlags(link, -1, int(DefaultXdpFlags)) failed: %v", err)
        }
        for {
                link, err = netlink.LinkByIndex(Ifindex)

I don't know if this is an artifact of my system, or if this is a more general issue, but if you think it's worth it I can make a PR.

MVP

I took this from one of the examples and modified/commented it to show the issue I'm seeing.

package main

import (
	"flag"
	"fmt"
	"net"

	"github.com/asavie/xdp"
	"golang.org/x/sys/unix"
)

func main() {
	var linkName string
	var queueID int

	flag.StringVar(&linkName, "linkname", "enp0s6f1", "The network link on which rebroadcast should run on.")
	flag.IntVar(&queueID, "queueid", 0, "The ID of the Rx queue to which to attach to on the network link.")
	flag.Parse()

	interfaces, err := net.Interfaces()
	if err != nil {
		fmt.Printf("error: failed to fetch the list of network interfaces on the system: %v\n", err)
		return
	}

	Ifindex := -1
	for _, iface := range interfaces {
		if iface.Name == linkName {
			Ifindex = iface.Index
			break
		}
	}
	if Ifindex == -1 {
		fmt.Printf("error: couldn't find a suitable network interface to attach to\n")
		return
	}

	// NOTE: The important bit!
	xdp.DefaultXdpFlags = unix.XDP_FLAGS_SKB_MODE

	fmt.Println("creating new program")
	program, err := xdp.NewProgram(queueID + 1)
	if err != nil {
		fmt.Printf("error: failed to create xdp program: %v\n", err)
		return
	}
	defer func() {
		fmt.Println("closing program")
		program.Close()
	}()

	fmt.Printf("attaching program to ifidx %d\n", Ifindex)
	if err := program.Attach(Ifindex); err != nil {
		fmt.Printf("error: failed to attach xdp program to interface: %v\n", err)
		return
	}
	defer func() {
		fmt.Println("detaching program")

		// NOTE: Without the diff above, this call hangs indefinitely
		program.Detach(Ifindex)
	}()

	fmt.Println("creating new XDP socket")
	xsk, err := xdp.NewSocket(Ifindex, queueID, nil)
	if err != nil {
		fmt.Printf("error: failed to create an XDP socket: %v\n", err)
		return
	}

	fmt.Println("registering socket with program")
	if err := program.Register(queueID, xsk.FD()); err != nil {
		fmt.Printf("error: failed to register socket in BPF map: %v\n", err)
		return
	}
	defer func() {
		fmt.Println("unregistering socket")
		program.Unregister(queueID)
	}()

	fmt.Println("done")
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant