Message ID | 20180713225451.5689-1-jakub.kicinski@netronome.com |
---|---|
State | Accepted, archived |
Delegated to: | David Ahern |
Headers | show |
Series | [iproute2-next,v2] iplink: add support for reporting multiple XDP programs | expand |
On 07/14/2018 12:54 AM, Jakub Kicinski wrote: > Kernel now supports attaching XDP programs in the driver > and hardware at the same time. Print that information > correctly. > > In case there are multiple programs attached kernel will > not provide IFLA_XDP_PROG_ID, so don't expect it to be > there (this also improves the printing for very old kernels > slightly, as it avoids unnecessary "prog/xdp" line). > > In short mode preserve the current outputs but don't print > IDs if there are multiple. > > 6: netdevsim0: <BROADCAST,NOARP> mtu 1500 xdpoffload/id:11 qdisc [...] > > and: > > 6: netdevsim0: <BROADCAST,NOARP> mtu 1500 xdpmulti qdisc [...] > > ip link output will keep using prog/xdp prefix if only one program > is attached, but can also print multiple program lines: > > prog/xdp id 8 tag fc7a51d1a693a99e jited > > vs: > > prog/xdpdrv id 8 tag fc7a51d1a693a99e jited > prog/xdpoffload id 9 tag fc7a51d1a693a99e > > JSON output gains a new array called "attached" which will > contain the full list of attached programs along with their > attachment modes: > > "xdp": { > "mode": 3, > "prog": { > "id": 11, > "tag": "fc7a51d1a693a99e", > "jited": 0 > }, > "attached": [ { > "mode": 3, > "prog": { > "id": 11, > "tag": "fc7a51d1a693a99e", > "jited": 0 > } > } ] > }, > > In case there are multiple programs attached the general "xdp" > section will not contain program information: > > "xdp": { > "mode": 4, > "attached": [ { > "mode": 1, > "prog": { > "id": 10, > "tag": "fc7a51d1a693a99e", > "jited": 1 > } > },{ > "mode": 3, > "prog": { > "id": 11, > "tag": "fc7a51d1a693a99e", > "jited": 0 > } > } ] > }, > > Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> > Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> LGTM, thanks! Acked-by: Daniel Borkmann <daniel@iogearbox.net>
On 7/13/18 4:54 PM, Jakub Kicinski wrote: > Kernel now supports attaching XDP programs in the driver > and hardware at the same time. Print that information > correctly. > > In case there are multiple programs attached kernel will > not provide IFLA_XDP_PROG_ID, so don't expect it to be > there (this also improves the printing for very old kernels > slightly, as it avoids unnecessary "prog/xdp" line). > ... > > Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> > Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> > --- > v2: > - const char * for constant string; > - add more compat for older kernels. > --- > ip/iplink_xdp.c | 73 +++++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 61 insertions(+), 12 deletions(-) > applied to iproute2-next. Thanks
diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c index dd4fd1fd3a3b..4a490bc8fb66 100644 --- a/ip/iplink_xdp.c +++ b/ip/iplink_xdp.c @@ -91,6 +91,18 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, 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; @@ -104,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); @@ -124,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); - } }