@@ -406,66 +406,19 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
406406 return 0 ;
407407}
408408
409- static int cls_bpf_set_parms (struct net * net , struct tcf_proto * tp ,
410- struct cls_bpf_prog * prog , unsigned long base ,
411- struct nlattr * * tb , struct nlattr * est , u32 flags ,
412- struct netlink_ext_ack * extack )
413- {
414- bool is_bpf , is_ebpf , have_exts = false;
415- u32 gen_flags = 0 ;
416- int ret ;
417-
418- is_bpf = tb [TCA_BPF_OPS_LEN ] && tb [TCA_BPF_OPS ];
419- is_ebpf = tb [TCA_BPF_FD ];
420- if ((!is_bpf && !is_ebpf ) || (is_bpf && is_ebpf ))
421- return - EINVAL ;
422-
423- ret = tcf_exts_validate (net , tp , tb , est , & prog -> exts , flags ,
424- extack );
425- if (ret < 0 )
426- return ret ;
427-
428- if (tb [TCA_BPF_FLAGS ]) {
429- u32 bpf_flags = nla_get_u32 (tb [TCA_BPF_FLAGS ]);
430-
431- if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT )
432- return - EINVAL ;
433-
434- have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT ;
435- }
436- if (tb [TCA_BPF_FLAGS_GEN ]) {
437- gen_flags = nla_get_u32 (tb [TCA_BPF_FLAGS_GEN ]);
438- if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
439- !tc_flags_valid (gen_flags ))
440- return - EINVAL ;
441- }
442-
443- prog -> exts_integrated = have_exts ;
444- prog -> gen_flags = gen_flags ;
445-
446- ret = is_bpf ? cls_bpf_prog_from_ops (tb , prog ) :
447- cls_bpf_prog_from_efd (tb , prog , gen_flags , tp );
448- if (ret < 0 )
449- return ret ;
450-
451- if (tb [TCA_BPF_CLASSID ]) {
452- prog -> res .classid = nla_get_u32 (tb [TCA_BPF_CLASSID ]);
453- tcf_bind_filter (tp , & prog -> res , base );
454- }
455-
456- return 0 ;
457- }
458-
459409static int cls_bpf_change (struct net * net , struct sk_buff * in_skb ,
460410 struct tcf_proto * tp , unsigned long base ,
461411 u32 handle , struct nlattr * * tca ,
462412 void * * arg , u32 flags ,
463413 struct netlink_ext_ack * extack )
464414{
465415 struct cls_bpf_head * head = rtnl_dereference (tp -> root );
416+ bool is_bpf , is_ebpf , have_exts = false;
466417 struct cls_bpf_prog * oldprog = * arg ;
467418 struct nlattr * tb [TCA_BPF_MAX + 1 ];
419+ bool bound_to_filter = false;
468420 struct cls_bpf_prog * prog ;
421+ u32 gen_flags = 0 ;
469422 int ret ;
470423
471424 if (tca [TCA_OPTIONS ] == NULL )
@@ -504,11 +457,51 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
504457 goto errout ;
505458 prog -> handle = handle ;
506459
507- ret = cls_bpf_set_parms (net , tp , prog , base , tb , tca [TCA_RATE ], flags ,
508- extack );
460+ is_bpf = tb [TCA_BPF_OPS_LEN ] && tb [TCA_BPF_OPS ];
461+ is_ebpf = tb [TCA_BPF_FD ];
462+ if ((!is_bpf && !is_ebpf ) || (is_bpf && is_ebpf )) {
463+ ret = - EINVAL ;
464+ goto errout_idr ;
465+ }
466+
467+ ret = tcf_exts_validate (net , tp , tb , tca [TCA_RATE ], & prog -> exts ,
468+ flags , extack );
469+ if (ret < 0 )
470+ goto errout_idr ;
471+
472+ if (tb [TCA_BPF_FLAGS ]) {
473+ u32 bpf_flags = nla_get_u32 (tb [TCA_BPF_FLAGS ]);
474+
475+ if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT ) {
476+ ret = - EINVAL ;
477+ goto errout_idr ;
478+ }
479+
480+ have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT ;
481+ }
482+ if (tb [TCA_BPF_FLAGS_GEN ]) {
483+ gen_flags = nla_get_u32 (tb [TCA_BPF_FLAGS_GEN ]);
484+ if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
485+ !tc_flags_valid (gen_flags )) {
486+ ret = - EINVAL ;
487+ goto errout_idr ;
488+ }
489+ }
490+
491+ prog -> exts_integrated = have_exts ;
492+ prog -> gen_flags = gen_flags ;
493+
494+ ret = is_bpf ? cls_bpf_prog_from_ops (tb , prog ) :
495+ cls_bpf_prog_from_efd (tb , prog , gen_flags , tp );
509496 if (ret < 0 )
510497 goto errout_idr ;
511498
499+ if (tb [TCA_BPF_CLASSID ]) {
500+ prog -> res .classid = nla_get_u32 (tb [TCA_BPF_CLASSID ]);
501+ tcf_bind_filter (tp , & prog -> res , base );
502+ bound_to_filter = true;
503+ }
504+
512505 ret = cls_bpf_offload (tp , prog , oldprog , extack );
513506 if (ret )
514507 goto errout_parms ;
@@ -530,6 +523,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
530523 return 0 ;
531524
532525errout_parms :
526+ if (bound_to_filter )
527+ tcf_unbind_filter (tp , & prog -> res );
533528 cls_bpf_free_parms (prog );
534529errout_idr :
535530 if (!oldprog )
0 commit comments