Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/sched: flower: Return error when hw can't offload and skip_sw is set

When skip_sw is set and hardware fails to apply filter, return error to
user. This will make error propagation logic similar to the one
currently used in u32 classifier.
Also, changed code to use tc_skip_sw() utility function.

Signed-off-by: Amir Vadai <amirva@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Amir Vadai and committed by
David S. Miller
e8eb36cd ce9355ac

+25 -17
+25 -17
net/sched/cls_flower.c
··· 140 140 f = rhashtable_lookup_fast(&head->ht, 141 141 fl_key_get_start(&skb_mkey, &head->mask), 142 142 head->ht_params); 143 - if (f && !(f->flags & TCA_CLS_FLAGS_SKIP_SW)) { 143 + if (f && !tc_skip_sw(f->flags)) { 144 144 *res = f->res; 145 145 return tcf_exts_exec(skb, &f->exts, res); 146 146 } ··· 187 187 dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc); 188 188 } 189 189 190 - static void fl_hw_replace_filter(struct tcf_proto *tp, 191 - struct flow_dissector *dissector, 192 - struct fl_flow_key *mask, 193 - struct fl_flow_key *key, 194 - struct tcf_exts *actions, 195 - unsigned long cookie, u32 flags) 190 + static int fl_hw_replace_filter(struct tcf_proto *tp, 191 + struct flow_dissector *dissector, 192 + struct fl_flow_key *mask, 193 + struct fl_flow_key *key, 194 + struct tcf_exts *actions, 195 + unsigned long cookie, u32 flags) 196 196 { 197 197 struct net_device *dev = tp->q->dev_queue->dev; 198 198 struct tc_cls_flower_offload offload = {0}; 199 199 struct tc_to_netdev tc; 200 + int err; 200 201 201 202 if (!tc_should_offload(dev, tp, flags)) 202 - return; 203 + return tc_skip_sw(flags) ? -EINVAL : 0; 203 204 204 205 offload.command = TC_CLSFLOWER_REPLACE; 205 206 offload.cookie = cookie; ··· 212 211 tc.type = TC_SETUP_CLSFLOWER; 213 212 tc.cls_flower = &offload; 214 213 215 - dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc); 214 + err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc); 215 + 216 + if (tc_skip_sw(flags)) 217 + return err; 218 + 219 + return 0; 216 220 } 217 221 218 222 static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f) ··· 578 572 if (err) 579 573 goto errout; 580 574 581 - if (!(fnew->flags & TCA_CLS_FLAGS_SKIP_SW)) { 575 + if (!tc_skip_sw(fnew->flags)) { 582 576 err = rhashtable_insert_fast(&head->ht, &fnew->ht_node, 583 577 head->ht_params); 584 578 if (err) 585 579 goto errout; 586 580 } 587 581 588 - fl_hw_replace_filter(tp, 589 - &head->dissector, 590 - &mask.key, 591 - &fnew->key, 592 - &fnew->exts, 593 - (unsigned long)fnew, 594 - fnew->flags); 582 + err = fl_hw_replace_filter(tp, 583 + &head->dissector, 584 + &mask.key, 585 + &fnew->key, 586 + &fnew->exts, 587 + (unsigned long)fnew, 588 + fnew->flags); 589 + if (err) 590 + goto errout; 595 591 596 592 if (fold) { 597 593 rhashtable_remove_fast(&head->ht, &fold->ht_node,