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

Detaching program hangs when using SKB mode #28

Open
@Crosse

Description

@Crosse

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")
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions