net: sched: cls_flower: implement offload tcf_proto_op
Add the reoffload tcf_proto_op in flower to generate an offload message for each filter in the given tcf_proto. Call the specified callback with this new offload message. The function only returns an error if the callback rejects adding a 'hardware only' rule. A filter contains a flag to indicate if it is in hardware or not. To ensure the reoffload function properly maintains this flag, keep a reference counter for the number of instances of the filter that are in hardware. Only update the flag when this counter changes from or to 0. Add a generic helper function to implement this behaviour. Signed-off-by: John Hurley <john.hurley@netronome.com> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									e56185c78b
								
							
						
					
					
						commit
						31533cba43
					
				| @ -336,6 +336,21 @@ static inline void tcf_block_offload_dec(struct tcf_block *block, u32 *flags) | ||||
| 	block->offloadcnt--; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| tc_cls_offload_cnt_update(struct tcf_block *block, unsigned int *cnt, | ||||
| 			  u32 *flags, bool add) | ||||
| { | ||||
| 	if (add) { | ||||
| 		if (!*cnt) | ||||
| 			tcf_block_offload_inc(block, flags); | ||||
| 		(*cnt)++; | ||||
| 	} else { | ||||
| 		(*cnt)--; | ||||
| 		if (!*cnt) | ||||
| 			tcf_block_offload_dec(block, flags); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) | ||||
| { | ||||
| 	struct qdisc_skb_cb *qcb; | ||||
|  | ||||
| @ -87,6 +87,7 @@ struct cls_fl_filter { | ||||
| 	struct list_head list; | ||||
| 	u32 handle; | ||||
| 	u32 flags; | ||||
| 	unsigned int in_hw_count; | ||||
| 	struct rcu_work rwork; | ||||
| 	struct net_device *hw_dev; | ||||
| }; | ||||
| @ -289,6 +290,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, | ||||
| 		fl_hw_destroy_filter(tp, f, NULL); | ||||
| 		return err; | ||||
| 	} else if (err > 0) { | ||||
| 		f->in_hw_count = err; | ||||
| 		tcf_block_offload_inc(block, &f->flags); | ||||
| 	} | ||||
| 
 | ||||
| @ -1087,6 +1089,47 @@ skip: | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, | ||||
| 			void *cb_priv, struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	struct cls_fl_head *head = rtnl_dereference(tp->root); | ||||
| 	struct tc_cls_flower_offload cls_flower = {}; | ||||
| 	struct tcf_block *block = tp->chain->block; | ||||
| 	struct fl_flow_mask *mask; | ||||
| 	struct cls_fl_filter *f; | ||||
| 	int err; | ||||
| 
 | ||||
| 	list_for_each_entry(mask, &head->masks, list) { | ||||
| 		list_for_each_entry(f, &mask->filters, list) { | ||||
| 			if (tc_skip_hw(f->flags)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			tc_cls_common_offload_init(&cls_flower.common, tp, | ||||
| 						   f->flags, extack); | ||||
| 			cls_flower.command = add ? | ||||
| 				TC_CLSFLOWER_REPLACE : TC_CLSFLOWER_DESTROY; | ||||
| 			cls_flower.cookie = (unsigned long)f; | ||||
| 			cls_flower.dissector = &mask->dissector; | ||||
| 			cls_flower.mask = &f->mkey; | ||||
| 			cls_flower.key = &f->key; | ||||
| 			cls_flower.exts = &f->exts; | ||||
| 			cls_flower.classid = f->res.classid; | ||||
| 
 | ||||
| 			err = cb(TC_SETUP_CLSFLOWER, &cls_flower, cb_priv); | ||||
| 			if (err) { | ||||
| 				if (add && tc_skip_sw(f->flags)) | ||||
| 					return err; | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			tc_cls_offload_cnt_update(block, &f->in_hw_count, | ||||
| 						  &f->flags, add); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int fl_dump_key_val(struct sk_buff *skb, | ||||
| 			   void *val, int val_type, | ||||
| 			   void *mask, int mask_type, int len) | ||||
| @ -1438,6 +1481,7 @@ static struct tcf_proto_ops cls_fl_ops __read_mostly = { | ||||
| 	.change		= fl_change, | ||||
| 	.delete		= fl_delete, | ||||
| 	.walk		= fl_walk, | ||||
| 	.reoffload	= fl_reoffload, | ||||
| 	.dump		= fl_dump, | ||||
| 	.bind_class	= fl_bind_class, | ||||
| 	.owner		= THIS_MODULE, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user