]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/iplink_xdp.c
iplink_can: add Classical CAN frame LEN8_DLC support
[mirror_iproute2.git] / ip / iplink_xdp.c
index 993e44d7878a756ffbeffa92cd4c2128cba30ad1..4a490bc8fb66c65448ba860355d8837be2eec3c0 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <linux/bpf.h>
 
-#include "json_print.h"
-#include "xdp.h"
 #include "bpf_util.h"
+#include "utils.h"
+#include "ip_common.h"
 
 extern int force;
 
@@ -48,8 +48,8 @@ static int xdp_delete(struct xdp_req *xdp)
        return 0;
 }
 
-int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
-             bool drv, bool offload)
+int xdp_parse(int *argc, char ***argv, struct iplink_req *req,
+             const char *ifname, bool generic, bool drv, bool offload)
 {
        struct bpf_cfg_in cfg = {
                .type = BPF_PROG_TYPE_XDP,
@@ -60,6 +60,14 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
                .req = req,
        };
 
+       if (offload) {
+               int ifindex = ll_name_to_index(ifname);
+
+               if (!ifindex)
+                       incomplete_command();
+               cfg.ifindex = ifindex;
+       }
+
        if (!force)
                xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
        if (generic)
@@ -75,7 +83,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
                        return xdp_delete(&xdp);
        }
 
-       if (bpf_parse_common(&cfg, &bpf_cb_ops, &xdp))
+       if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &xdp))
                return -1;
 
        *argc = cfg.argc;
@@ -83,6 +91,18 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
        return 0;
 }
 
+static void xdp_dump_json_one(struct rtattr *tb[IFLA_XDP_MAX + 1], __u32 attr,
+                             __u8 mode)
+{
+       if (!tb[attr])
+               return;
+
+       open_json_object(NULL);
+       print_uint(PRINT_JSON, "mode", NULL, mode);
+       bpf_dump_prog_info(NULL, rta_getattr_u32(tb[attr]));
+       close_json_object();
+}
+
 static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1])
 {
        __u32 prog_id = 0;
@@ -96,13 +116,48 @@ static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1])
        print_uint(PRINT_JSON, "mode", NULL, mode);
        if (prog_id)
                bpf_dump_prog_info(NULL, prog_id);
+
+       open_json_array(PRINT_JSON, "attached");
+       if (tb[IFLA_XDP_SKB_PROG_ID] ||
+           tb[IFLA_XDP_DRV_PROG_ID] ||
+           tb[IFLA_XDP_HW_PROG_ID]) {
+               xdp_dump_json_one(tb, IFLA_XDP_SKB_PROG_ID, XDP_ATTACHED_SKB);
+               xdp_dump_json_one(tb, IFLA_XDP_DRV_PROG_ID, XDP_ATTACHED_DRV);
+               xdp_dump_json_one(tb, IFLA_XDP_HW_PROG_ID, XDP_ATTACHED_HW);
+       } else if (tb[IFLA_XDP_PROG_ID]) {
+               /* Older kernel - use IFLA_XDP_PROG_ID */
+               xdp_dump_json_one(tb, IFLA_XDP_PROG_ID, mode);
+       }
+       close_json_array(PRINT_JSON, NULL);
+
        close_json_object();
 }
 
+static void xdp_dump_prog_one(FILE *fp, struct rtattr *tb[IFLA_XDP_MAX + 1],
+                             __u32 attr, bool link, bool details,
+                             const char *pfx)
+{
+       __u32 prog_id;
+
+       if (!tb[attr])
+               return;
+
+       prog_id = rta_getattr_u32(tb[attr]);
+       if (!details) {
+               if (prog_id && !link && attr == IFLA_XDP_PROG_ID)
+                       fprintf(fp, "/id:%u", prog_id);
+               return;
+       }
+
+       if (prog_id) {
+               fprintf(fp, "%s    prog/xdp%s ", _SL_, pfx);
+               bpf_dump_prog_info(fp, prog_id);
+       }
+}
+
 void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
 {
        struct rtattr *tb[IFLA_XDP_MAX + 1];
-       __u32 prog_id = 0;
        __u8 mode;
 
        parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp);
@@ -116,27 +171,29 @@ void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
        else if (is_json_context())
                return details ? (void)0 : xdp_dump_json(tb);
        else if (details && link)
-               fprintf(fp, "%s    prog/xdp", _SL_);
+               /* don't print mode */;
        else if (mode == XDP_ATTACHED_DRV)
                fprintf(fp, "xdp");
        else if (mode == XDP_ATTACHED_SKB)
                fprintf(fp, "xdpgeneric");
        else if (mode == XDP_ATTACHED_HW)
                fprintf(fp, "xdpoffload");
+       else if (mode == XDP_ATTACHED_MULTI)
+               fprintf(fp, "xdpmulti");
        else
                fprintf(fp, "xdp[%u]", mode);
 
-       if (tb[IFLA_XDP_PROG_ID])
-               prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
-       if (!details) {
-               if (prog_id && !link)
-                       fprintf(fp, "/id:%u", prog_id);
-               fprintf(fp, " ");
-               return;
+       xdp_dump_prog_one(fp, tb, IFLA_XDP_PROG_ID, link, details, "");
+
+       if (mode == XDP_ATTACHED_MULTI) {
+               xdp_dump_prog_one(fp, tb, IFLA_XDP_SKB_PROG_ID, link, details,
+                                 "generic");
+               xdp_dump_prog_one(fp, tb, IFLA_XDP_DRV_PROG_ID, link, details,
+                                 "drv");
+               xdp_dump_prog_one(fp, tb, IFLA_XDP_HW_PROG_ID, link, details,
+                                 "offload");
        }
 
-       if (prog_id) {
+       if (!details || !link)
                fprintf(fp, " ");
-               bpf_dump_prog_info(fp, prog_id);
-       }
 }