Re: [PATCHv3 bpf-next] samples/bpf: add xdp program on egress for xdp_redirect_map
From: Jesper Dangaard Brouer <hidden>
Date: 2020-12-08 10:40:59
Also in:
bpf
On Tue, 8 Dec 2020 16:18:56 +0800 Hangbin Liu [off-list ref] wrote:
This patch add a xdp program on egress to show that we can modify the packet on egress. In this sample we will set the pkt's src mac to egress's mac address. The xdp_prog will be attached when -X option supplied. Signed-off-by: Hangbin Liu <redacted> --- v3: a) modify the src mac address based on egress mac v2: a) use pkt counter instead of IP ttl modification on egress program b) make the egress program selectable by option -X --- samples/bpf/xdp_redirect_map_kern.c | 60 ++++++++++- samples/bpf/xdp_redirect_map_user.c | 153 ++++++++++++++++++++-------- 2 files changed, 168 insertions(+), 45 deletions(-)
[...]
quoted hunk ↗ jump to hunk
diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c index 31131b6e7782..19636045c8dc 100644 --- a/samples/bpf/xdp_redirect_map_user.c +++ b/samples/bpf/xdp_redirect_map_user.c@@ -14,6 +14,10 @@ #include <unistd.h> #include <libgen.h> #include <sys/resource.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> #include "bpf_util.h" #include <bpf/bpf.h>@@ -21,7 +25,8 @@ static int ifindex_in; static int ifindex_out; -static bool ifindex_out_xdp_dummy_attached = true; +static bool ifindex_out_xdp_dummy_attached = false; +static bool xdp_devmap_attached = false; static __u32 prog_id; static __u32 dummy_prog_id;@@ -83,6 +88,29 @@ static void poll_stats(int interval, int ifindex) } } +static int get_mac_addr(unsigned int ifindex_out, void *mac_addr) +{ + struct ifreq ifr; + char ifname[IF_NAMESIZE]; + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
I would have expected (like ethtool): fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) + return -1; + + if (!if_indextoname(ifindex_out, ifname)) + return -1; + + strcpy(ifr.ifr_name, ifname); + + if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0) + return -1; + + memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6 * sizeof(char)); + close(fd); + + return 0; +}
[...]
- /* Loading dummy XDP prog on out-device */
- if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
- (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
- printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
- ifindex_out_xdp_dummy_attached = false;
- }
+ /* If -X supplied, load 2nd xdp prog on egress.
+ * If not, just load dummy prog on egress.
+ */The dummy prog need to be loaded, regardless of 2nd xdp prog on egress.
+ if (xdp_devmap_attached) {
+ unsigned char mac_addr[6];
- memset(&info, 0, sizeof(info));
- ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len);
- if (ret) {
- printf("can't get prog info - %s\n", strerror(errno));
- return ret;
+ devmap_prog = bpf_object__find_program_by_title(obj, "xdp_devmap/map_prog");
+ if (!devmap_prog) {
+ printf("finding devmap_prog in obj file failed\n");
+ goto out;
+ }
+ devmap_prog_fd = bpf_program__fd(devmap_prog);
+ if (devmap_prog_fd < 0) {
+ printf("finding devmap_prog fd failed\n");
+ goto out;
+ }
+
+ if (get_mac_addr(ifindex_out, mac_addr) < 0) {
+ printf("get interface %d mac failed\n", ifindex_out);
+ goto out;
+ }
+
+ ret = bpf_map_update_elem(tx_mac_map_fd, &key, mac_addr, 0);
+ if (ret) {
+ perror("bpf_update_elem tx_mac_map_fd");
+ goto out;
+ }
+ } else if (ifindex_in != ifindex_out) {
+ dummy_prog = bpf_object__find_program_by_title(obj, "xdp_redirect_dummy");
+ if (!dummy_prog) {
+ printf("finding dummy_prog in obj file failed\n");
+ goto out;
+ }
+
+ dummy_prog_fd = bpf_program__fd(dummy_prog);
+ if (dummy_prog_fd < 0) {
+ printf("find dummy_prog fd failed\n");
+ goto out;
+ }
+
+ if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
+ (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) == 0) {
+ ifindex_out_xdp_dummy_attached = true;
+ } else {
+ printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
+ }
+
+ memset(&info, 0, sizeof(info));
+ ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ }
+ dummy_prog_id = info.id;
}
- dummy_prog_id = info.id;
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
- /* populate virtual to physical port map */
- ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
+ devmap_val.ifindex = ifindex_out;
+ devmap_val.bpf_prog.fd = devmap_prog_fd;
+ ret = bpf_map_update_elem(tx_port_map_fd, &key, &devmap_val, 0);
if (ret) {
- perror("bpf_update_elem");
+ perror("bpf_update_elem tx_port_map_fd");
goto out;
}
poll_stats(2, ifindex_out);
out:
- return 0;
+ bpf_object__close(obj);
+ return 1;
}-- Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer