Skip to content

Conversation

noguxun
Copy link

@noguxun noguxun commented Sep 20, 2025

  • Implemented TODO: unloading & unpinning
  • Reimplemented the assignment 2: map use, according to the readme

*map_reused = false;

/* 1) First, try to reuse maps by opening object and reusing before libxdp creates it */
struct bpf_object *obj = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep all variable declarations at the top of the function

}
}

return EXIT_OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though the program exits, it is good practice to explicitly clean up resources before exiting. So please add xdp_program__close() and bpf_object__close() calls before returning :)

(And yeah, I realise this bug was already there for xdp_program, but let's use this opportunity to fix it)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, added the close of resources in the new push.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Except this is not hit in the error path of the !map_reused branch. That return needs to be replaced with a goto out, and the final return should be using the value of err.

return err;
}

return EXIT_OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and same thing here wrt returning without an explicit close.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did the same in the new push, Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, same comment about the error branch, though :)

Copy link
Member

@tohojo tohojo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few error branches that are not handled correctly; and a comment on restructuring the loading code that would make things simpler...

err = xdp_program__attach(prog, cfg->ifindex, cfg->attach_mode, 0);
if (err) {
fprintf(stderr, "ERR: xdp_program__attach: %s\n", strerror(-err));
xdp_program__close(prog);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't close the bpf_object.

Thinking about this some more, separating out the opening of the BPF object seems to just be unneeded complexity; we might as well just open the object through libxdp, then access it through the xdp_program pointer afterwards. That simplifies the state handling because the xdp_program will own the bpf_object reference, and we only need to keep track of one thing.

So something like:

DECLARE_LIBXDP_OPTS(xdp_program_opts, xdp_opts, 
  .prog_name = cfg->progname,
  .open_filename = cfg->filename);
prog = xdp_program__create(&xdp_opts);
if (!prog)
  return -errno;

map = bpf_object__find_map_by_name(xdp_program__bpf_obj(prog), map_name));
if (!map) {
  fprintf(stderr, "Map %s not found!\n", map_name);
  xdp_program__close(prog);
  return -ENOENT;
}

// reuse map

err = xdp_program__attach(...).
// etc

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the line below is executed, my understanding is that xdp has created the BPF object and it's map.

DECLARE_LIBXDP_OPTS(xdp_program_opts, xdp_opts, 
  .prog_name = cfg->progname,
  .open_filename = cfg->filename);
prog = xdp_program__create(&xdp_opts);

Then we try to reuse the pinned map. What will happen to the newly created map (with the BPF object)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or my understanding is wrong. bpf's map creation actually happens when xdp_program__attach is called?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some comments at

/* At this point: BPF-progs are (only) loaded by the kernel, and prog_fd
* is our select file-descriptor handle. Next step is attaching this FD
* to a kernel hook point, in this case XDP net_device link-level hook.
*/
err = xdp_program__attach(prog, cfg->ifindex, cfg->attach_mode, 0);

It sounds like the BPF object is already loaded before the XDP attach is called.
But I checked the libxdp code, it seems BPF load is called in the XDP attach, not the create.

If your suggestion works (which means the BPF object is loaded in the attachment), this comment needs to be fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, looks like that comment is left-over from before the conversion to libxdp. At that point it was accurate, today it's wrong (i.e., libxdp doesn't load the bpf_object into the kernel until xdp_program__attach() is called)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tohojo , Thanks for the review.
I have a new push to the PR, according to your review.

}
}

return EXIT_OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Except this is not hit in the error path of the !map_reused branch. That return needs to be replaced with a goto out, and the final return should be using the value of err.

return err;
}

return EXIT_OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, same comment about the error branch, though :)

@noguxun noguxun force-pushed the basic04 branch 3 times, most recently from b3c40d8 to 1e57b42 Compare October 2, 2025 05:29
/* Initialize the pin_dir configuration */
len = snprintf(cfg.pin_dir, 512, "%s/%s", pin_basedir, cfg.ifname);
/* Try to reuse existing pinned maps before loading */
len = snprintf(path, PATH_MAX, "%s/%s", pin_basedir, cfg.ifname);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this? You're adding a bunch of code duplication by building the path multiple times instead of just reusing cfg->pin_dir everywhere as the code was doing before...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is because I want to implement the solution based on basic04 xdp_loader.c , in which cfg.pin_dir is not implemented. Also it looks like there are a lot of changes in pin_maps_in_bpf_object function in the solution folder. But actually, it is the same as what is in basic04.

But I do think implementation in basic-solution is better than basic04.
Maybe I can merge basic-solution's implementation to basic04.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They don't have to be completely identical, just enough that one can go look at the solution if one gets stuck on completing the assignment. So something like the use of the config struct is fine to divert on...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be fixed in the new push.

"Unload XDP program instead of loading"},

{{"reuse-maps", no_argument, NULL, 'M' },
"Reuse pinned maps"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove the reuse-maps option?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current version's reuse-map is used for map pinning.
This does not look like what is needed for the assignment 2.
So I delete it completely as the assignment does not mention to create a on/off switch.

	if (!cfg.reuse_maps) {
		err = pin_maps_in_bpf_object(xdp_program__bpf_obj(program), &cfg);
		if (err) {
			fprintf(stderr, "ERR: pinning maps\n");
			return err;
		}
	}

If a flag is needed, I can add it back and put it around map-reuse code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the intention of the option is: If the option set, try to reuse maps if they already exist, and if not, pin them. If the option is not set, do neither (no reuse, no pinning)...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That make sense!
I just had a new push to implement above logic. Thanks for the explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants