naccyde / rpms / iproute

Forked from rpms/iproute a year ago
Clone

Blame SOURCES/0055-iplink-add-support-for-reporting-multiple-XDP-progra.patch

8def76
From 907e2adbcb6e02453972d5ada93de7bbaefedb2a Mon Sep 17 00:00:00 2001
8def76
From: Andrea Claudi <aclaudi@redhat.com>
8def76
Date: Thu, 13 Jun 2019 14:37:56 +0200
8def76
Subject: [PATCH] iplink: add support for reporting multiple XDP programs
8def76
8def76
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361
8def76
Upstream Status: iproute2.git commit da083b5a483bf
8def76
8def76
commit da083b5a483bfd52dfe72912f62a3bc16d775b87
8def76
Author: Jakub Kicinski <jakub.kicinski@netronome.com>
8def76
Date:   Fri Jul 13 15:54:51 2018 -0700
8def76
8def76
    iplink: add support for reporting multiple XDP programs
8def76
8def76
    Kernel now supports attaching XDP programs in the driver
8def76
    and hardware at the same time.  Print that information
8def76
    correctly.
8def76
8def76
    In case there are multiple programs attached kernel will
8def76
    not provide IFLA_XDP_PROG_ID, so don't expect it to be
8def76
    there (this also improves the printing for very old kernels
8def76
    slightly, as it avoids unnecessary "prog/xdp" line).
8def76
8def76
    In short mode preserve the current outputs but don't print
8def76
    IDs if there are multiple.
8def76
8def76
    6: netdevsim0: <BROADCAST,NOARP> mtu 1500 xdpoffload/id:11 qdisc [...]
8def76
8def76
    and:
8def76
8def76
    6: netdevsim0: <BROADCAST,NOARP> mtu 1500 xdpmulti qdisc [...]
8def76
8def76
    ip link output will keep using prog/xdp prefix if only one program
8def76
    is attached, but can also print multiple program lines:
8def76
8def76
        prog/xdp id 8 tag fc7a51d1a693a99e jited
8def76
8def76
    vs:
8def76
8def76
        prog/xdpdrv id 8 tag fc7a51d1a693a99e jited
8def76
        prog/xdpoffload id 9 tag fc7a51d1a693a99e
8def76
8def76
    JSON output gains a new array called "attached" which will
8def76
    contain the full list of attached programs along with their
8def76
    attachment modes:
8def76
8def76
            "xdp": {
8def76
                "mode": 3,
8def76
                "prog": {
8def76
                    "id": 11,
8def76
                    "tag": "fc7a51d1a693a99e",
8def76
                    "jited": 0
8def76
                },
8def76
                "attached": [ {
8def76
                        "mode": 3,
8def76
                        "prog": {
8def76
                            "id": 11,
8def76
                            "tag": "fc7a51d1a693a99e",
8def76
                            "jited": 0
8def76
                        }
8def76
                    } ]
8def76
            },
8def76
8def76
    In case there are multiple programs attached the general "xdp"
8def76
    section will not contain program information:
8def76
8def76
            "xdp": {
8def76
                "mode": 4,
8def76
                "attached": [ {
8def76
                        "mode": 1,
8def76
                        "prog": {
8def76
                            "id": 10,
8def76
                            "tag": "fc7a51d1a693a99e",
8def76
                            "jited": 1
8def76
                        }
8def76
                    },{
8def76
                        "mode": 3,
8def76
                        "prog": {
8def76
                            "id": 11,
8def76
                            "tag": "fc7a51d1a693a99e",
8def76
                            "jited": 0
8def76
                        }
8def76
                    } ]
8def76
            },
8def76
8def76
    Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
8def76
    Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
8def76
    Acked-by: Daniel Borkmann <daniel@iogearbox.net>
8def76
    Signed-off-by: David Ahern <dsahern@gmail.com>
8def76
---
8def76
 ip/iplink_xdp.c | 73 +++++++++++++++++++++++++++++++++++++++++--------
8def76
 1 file changed, 61 insertions(+), 12 deletions(-)
8def76
8def76
diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c
8def76
index dd4fd1fd3a3b1..4a490bc8fb66c 100644
8def76
--- a/ip/iplink_xdp.c
8def76
+++ b/ip/iplink_xdp.c
8def76
@@ -91,6 +91,18 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req,
8def76
 	return 0;
8def76
 }
8def76
 
8def76
+static void xdp_dump_json_one(struct rtattr *tb[IFLA_XDP_MAX + 1], __u32 attr,
8def76
+			      __u8 mode)
8def76
+{
8def76
+	if (!tb[attr])
8def76
+		return;
8def76
+
8def76
+	open_json_object(NULL);
8def76
+	print_uint(PRINT_JSON, "mode", NULL, mode);
8def76
+	bpf_dump_prog_info(NULL, rta_getattr_u32(tb[attr]));
8def76
+	close_json_object();
8def76
+}
8def76
+
8def76
 static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1])
8def76
 {
8def76
 	__u32 prog_id = 0;
8def76
@@ -104,13 +116,48 @@ static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1])
8def76
 	print_uint(PRINT_JSON, "mode", NULL, mode);
8def76
 	if (prog_id)
8def76
 		bpf_dump_prog_info(NULL, prog_id);
8def76
+
8def76
+	open_json_array(PRINT_JSON, "attached");
8def76
+	if (tb[IFLA_XDP_SKB_PROG_ID] ||
8def76
+	    tb[IFLA_XDP_DRV_PROG_ID] ||
8def76
+	    tb[IFLA_XDP_HW_PROG_ID]) {
8def76
+		xdp_dump_json_one(tb, IFLA_XDP_SKB_PROG_ID, XDP_ATTACHED_SKB);
8def76
+		xdp_dump_json_one(tb, IFLA_XDP_DRV_PROG_ID, XDP_ATTACHED_DRV);
8def76
+		xdp_dump_json_one(tb, IFLA_XDP_HW_PROG_ID, XDP_ATTACHED_HW);
8def76
+	} else if (tb[IFLA_XDP_PROG_ID]) {
8def76
+		/* Older kernel - use IFLA_XDP_PROG_ID */
8def76
+		xdp_dump_json_one(tb, IFLA_XDP_PROG_ID, mode);
8def76
+	}
8def76
+	close_json_array(PRINT_JSON, NULL);
8def76
+
8def76
 	close_json_object();
8def76
 }
8def76
 
8def76
+static void xdp_dump_prog_one(FILE *fp, struct rtattr *tb[IFLA_XDP_MAX + 1],
8def76
+			      __u32 attr, bool link, bool details,
8def76
+			      const char *pfx)
8def76
+{
8def76
+	__u32 prog_id;
8def76
+
8def76
+	if (!tb[attr])
8def76
+		return;
8def76
+
8def76
+	prog_id = rta_getattr_u32(tb[attr]);
8def76
+	if (!details) {
8def76
+		if (prog_id && !link && attr == IFLA_XDP_PROG_ID)
8def76
+			fprintf(fp, "/id:%u", prog_id);
8def76
+		return;
8def76
+	}
8def76
+
8def76
+	if (prog_id) {
8def76
+		fprintf(fp, "%s    prog/xdp%s ", _SL_, pfx);
8def76
+		bpf_dump_prog_info(fp, prog_id);
8def76
+	}
8def76
+}
8def76
+
8def76
 void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
8def76
 {
8def76
 	struct rtattr *tb[IFLA_XDP_MAX + 1];
8def76
-	__u32 prog_id = 0;
8def76
 	__u8 mode;
8def76
 
8def76
 	parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp);
8def76
@@ -124,27 +171,29 @@ void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
8def76
 	else if (is_json_context())
8def76
 		return details ? (void)0 : xdp_dump_json(tb);
8def76
 	else if (details && link)
8def76
-		fprintf(fp, "%s    prog/xdp", _SL_);
8def76
+		/* don't print mode */;
8def76
 	else if (mode == XDP_ATTACHED_DRV)
8def76
 		fprintf(fp, "xdp");
8def76
 	else if (mode == XDP_ATTACHED_SKB)
8def76
 		fprintf(fp, "xdpgeneric");
8def76
 	else if (mode == XDP_ATTACHED_HW)
8def76
 		fprintf(fp, "xdpoffload");
8def76
+	else if (mode == XDP_ATTACHED_MULTI)
8def76
+		fprintf(fp, "xdpmulti");
8def76
 	else
8def76
 		fprintf(fp, "xdp[%u]", mode);
8def76
 
8def76
-	if (tb[IFLA_XDP_PROG_ID])
8def76
-		prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
8def76
-	if (!details) {
8def76
-		if (prog_id && !link)
8def76
-			fprintf(fp, "/id:%u", prog_id);
8def76
-		fprintf(fp, " ");
8def76
-		return;
8def76
+	xdp_dump_prog_one(fp, tb, IFLA_XDP_PROG_ID, link, details, "");
8def76
+
8def76
+	if (mode == XDP_ATTACHED_MULTI) {
8def76
+		xdp_dump_prog_one(fp, tb, IFLA_XDP_SKB_PROG_ID, link, details,
8def76
+				  "generic");
8def76
+		xdp_dump_prog_one(fp, tb, IFLA_XDP_DRV_PROG_ID, link, details,
8def76
+				  "drv");
8def76
+		xdp_dump_prog_one(fp, tb, IFLA_XDP_HW_PROG_ID, link, details,
8def76
+				  "offload");
8def76
 	}
8def76
 
8def76
-	if (prog_id) {
8def76
+	if (!details || !link)
8def76
 		fprintf(fp, " ");
8def76
-		bpf_dump_prog_info(fp, prog_id);
8def76
-	}
8def76
 }
8def76
-- 
8def76
2.20.1
8def76