@@ -55,6 +55,35 @@ struct bpf_attach_info {
5555 __u32 flow_dissector_id ;
5656};
5757
58+ enum net_attach_type {
59+ NET_ATTACH_TYPE_XDP ,
60+ NET_ATTACH_TYPE_XDP_GENERIC ,
61+ NET_ATTACH_TYPE_XDP_DRIVER ,
62+ NET_ATTACH_TYPE_XDP_OFFLOAD ,
63+ };
64+
65+ static const char * const attach_type_strings [] = {
66+ [NET_ATTACH_TYPE_XDP ] = "xdp" ,
67+ [NET_ATTACH_TYPE_XDP_GENERIC ] = "xdpgeneric" ,
68+ [NET_ATTACH_TYPE_XDP_DRIVER ] = "xdpdrv" ,
69+ [NET_ATTACH_TYPE_XDP_OFFLOAD ] = "xdpoffload" ,
70+ };
71+
72+ const size_t net_attach_type_size = ARRAY_SIZE (attach_type_strings );
73+
74+ static enum net_attach_type parse_attach_type (const char * str )
75+ {
76+ enum net_attach_type type ;
77+
78+ for (type = 0 ; type < net_attach_type_size ; type ++ ) {
79+ if (attach_type_strings [type ] &&
80+ is_prefix (str , attach_type_strings [type ]))
81+ return type ;
82+ }
83+
84+ return net_attach_type_size ;
85+ }
86+
5887static int dump_link_nlmsg (void * cookie , void * msg , struct nlattr * * tb )
5988{
6089 struct bpf_netdev_t * netinfo = cookie ;
@@ -223,6 +252,97 @@ static int query_flow_dissector(struct bpf_attach_info *attach_info)
223252 return 0 ;
224253}
225254
255+ static int net_parse_dev (int * argc , char * * * argv )
256+ {
257+ int ifindex ;
258+
259+ if (is_prefix (* * argv , "dev" )) {
260+ NEXT_ARGP ();
261+
262+ ifindex = if_nametoindex (* * argv );
263+ if (!ifindex )
264+ p_err ("invalid devname %s" , * * argv );
265+
266+ NEXT_ARGP ();
267+ } else {
268+ p_err ("expected 'dev', got: '%s'?" , * * argv );
269+ return -1 ;
270+ }
271+
272+ return ifindex ;
273+ }
274+
275+ static int do_attach_detach_xdp (int progfd , enum net_attach_type attach_type ,
276+ int ifindex , bool overwrite )
277+ {
278+ __u32 flags = 0 ;
279+
280+ if (!overwrite )
281+ flags = XDP_FLAGS_UPDATE_IF_NOEXIST ;
282+ if (attach_type == NET_ATTACH_TYPE_XDP_GENERIC )
283+ flags |= XDP_FLAGS_SKB_MODE ;
284+ if (attach_type == NET_ATTACH_TYPE_XDP_DRIVER )
285+ flags |= XDP_FLAGS_DRV_MODE ;
286+ if (attach_type == NET_ATTACH_TYPE_XDP_OFFLOAD )
287+ flags |= XDP_FLAGS_HW_MODE ;
288+
289+ return bpf_set_link_xdp_fd (ifindex , progfd , flags );
290+ }
291+
292+ static int do_attach (int argc , char * * argv )
293+ {
294+ enum net_attach_type attach_type ;
295+ int progfd , ifindex , err = 0 ;
296+ bool overwrite = false;
297+
298+ /* parse attach args */
299+ if (!REQ_ARGS (5 ))
300+ return - EINVAL ;
301+
302+ attach_type = parse_attach_type (* argv );
303+ if (attach_type == net_attach_type_size ) {
304+ p_err ("invalid net attach/detach type: %s" , * argv );
305+ return - EINVAL ;
306+ }
307+ NEXT_ARG ();
308+
309+ progfd = prog_parse_fd (& argc , & argv );
310+ if (progfd < 0 )
311+ return - EINVAL ;
312+
313+ ifindex = net_parse_dev (& argc , & argv );
314+ if (ifindex < 1 ) {
315+ close (progfd );
316+ return - EINVAL ;
317+ }
318+
319+ if (argc ) {
320+ if (is_prefix (* argv , "overwrite" )) {
321+ overwrite = true;
322+ } else {
323+ p_err ("expected 'overwrite', got: '%s'?" , * argv );
324+ close (progfd );
325+ return - EINVAL ;
326+ }
327+ }
328+
329+ /* attach xdp prog */
330+ if (is_prefix ("xdp" , attach_type_strings [attach_type ]))
331+ err = do_attach_detach_xdp (progfd , attach_type , ifindex ,
332+ overwrite );
333+
334+ if (err < 0 ) {
335+ p_err ("interface %s attach failed: %s" ,
336+ attach_type_strings [attach_type ], strerror (- err ));
337+ return err ;
338+ }
339+
340+ if (json_output )
341+ jsonw_null (json_wtr );
342+
343+ return 0 ;
344+ }
345+
226346static int do_show (int argc , char * * argv )
227347{
228348 struct bpf_attach_info attach_info = {};
@@ -232,13 +352,9 @@ static int do_show(int argc, char **argv)
232352 char err_buf [256 ];
233353
234354 if (argc == 2 ) {
235- if (strcmp (argv [0 ], "dev" ) != 0 )
236- usage ();
237- filter_idx = if_nametoindex (argv [1 ]);
238- if (filter_idx == 0 ) {
239- fprintf (stderr , "invalid dev name %s\n" , argv [1 ]);
355+ filter_idx = net_parse_dev (& argc , & argv );
356+ if (filter_idx < 1 )
240357 return -1 ;
241- }
242358 } else if (argc != 0 ) {
243359 usage ();
244360 }
@@ -305,20 +421,26 @@ static int do_help(int argc, char **argv)
305421
306422 fprintf (stderr ,
307423 "Usage: %s %s { show | list } [dev <devname>]\n"
424+ " %s %s attach ATTACH_TYPE PROG dev <devname> [ overwrite ]\n"
308425 " %s %s help\n"
426+ "\n"
427+ " " HELP_SPEC_PROGRAM "\n"
428+ " ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload }\n"
429+ "\n"
309430 "Note: Only xdp and tc attachments are supported now.\n"
310431 " For progs attached to cgroups, use \"bpftool cgroup\"\n"
311432 " to dump program attachments. For program types\n"
312433 " sk_{filter,skb,msg,reuseport} and lwt/seg6, please\n"
313434 " consult iproute2.\n" ,
314- bin_name , argv [-2 ], bin_name , argv [-2 ]);
435+ bin_name , argv [-2 ], bin_name , argv [-2 ], bin_name , argv [ -2 ] );
315436
316437 return 0 ;
317438}
318439
319440static const struct cmd cmds [] = {
320441 { "show" , do_show },
321442 { "list" , do_show },
443+ { "attach" , do_attach },
322444 { "help" , do_help },
323445 { 0 }
324446};
0 commit comments