1*c9da1ac1SSteen Hegelund // SPDX-License-Identifier: GPL-2.0+
2*c9da1ac1SSteen Hegelund /* Microchip VCAP API
3*c9da1ac1SSteen Hegelund  *
4*c9da1ac1SSteen Hegelund  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
5*c9da1ac1SSteen Hegelund  */
6*c9da1ac1SSteen Hegelund 
7*c9da1ac1SSteen Hegelund #include <linux/types.h>
8*c9da1ac1SSteen Hegelund 
9*c9da1ac1SSteen Hegelund #include "vcap_api.h"
10*c9da1ac1SSteen Hegelund #include "vcap_api_client.h"
11*c9da1ac1SSteen Hegelund 
12*c9da1ac1SSteen Hegelund #define to_intrule(rule) container_of((rule), struct vcap_rule_internal, data)
13*c9da1ac1SSteen Hegelund 
14*c9da1ac1SSteen Hegelund /* Private VCAP API rule data */
15*c9da1ac1SSteen Hegelund struct vcap_rule_internal {
16*c9da1ac1SSteen Hegelund 	struct vcap_rule data; /* provided by the client */
17*c9da1ac1SSteen Hegelund 	struct list_head list; /* for insertion in the vcap admin list of rules */
18*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin; /* vcap hw instance */
19*c9da1ac1SSteen Hegelund 	struct net_device *ndev;  /* the interface that the rule applies to */
20*c9da1ac1SSteen Hegelund 	struct vcap_control *vctrl; /* the client control */
21*c9da1ac1SSteen Hegelund 	u32 addr; /* address in the VCAP at insertion */
22*c9da1ac1SSteen Hegelund };
23*c9da1ac1SSteen Hegelund 
24*c9da1ac1SSteen Hegelund /* Update the keyset for the rule */
25*c9da1ac1SSteen Hegelund int vcap_set_rule_set_keyset(struct vcap_rule *rule,
26*c9da1ac1SSteen Hegelund 			     enum vcap_keyfield_set keyset)
27*c9da1ac1SSteen Hegelund {
28*c9da1ac1SSteen Hegelund 	/* This will be expanded with more information later */
29*c9da1ac1SSteen Hegelund 	rule->keyset = keyset;
30*c9da1ac1SSteen Hegelund 	return 0;
31*c9da1ac1SSteen Hegelund }
32*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_set_rule_set_keyset);
33*c9da1ac1SSteen Hegelund 
34*c9da1ac1SSteen Hegelund /* Update the actionset for the rule */
35*c9da1ac1SSteen Hegelund int vcap_set_rule_set_actionset(struct vcap_rule *rule,
36*c9da1ac1SSteen Hegelund 				enum vcap_actionfield_set actionset)
37*c9da1ac1SSteen Hegelund {
38*c9da1ac1SSteen Hegelund 	/* This will be expanded with more information later */
39*c9da1ac1SSteen Hegelund 	rule->actionset = actionset;
40*c9da1ac1SSteen Hegelund 	return 0;
41*c9da1ac1SSteen Hegelund }
42*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_set_rule_set_actionset);
43*c9da1ac1SSteen Hegelund 
44*c9da1ac1SSteen Hegelund /* Find a rule with a provided rule id */
45*c9da1ac1SSteen Hegelund static struct vcap_rule_internal *vcap_lookup_rule(struct vcap_control *vctrl,
46*c9da1ac1SSteen Hegelund 						   u32 id)
47*c9da1ac1SSteen Hegelund {
48*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri;
49*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin;
50*c9da1ac1SSteen Hegelund 
51*c9da1ac1SSteen Hegelund 	/* Look for the rule id in all vcaps */
52*c9da1ac1SSteen Hegelund 	list_for_each_entry(admin, &vctrl->list, list)
53*c9da1ac1SSteen Hegelund 		list_for_each_entry(ri, &admin->rules, list)
54*c9da1ac1SSteen Hegelund 			if (ri->data.id == id)
55*c9da1ac1SSteen Hegelund 				return ri;
56*c9da1ac1SSteen Hegelund 	return NULL;
57*c9da1ac1SSteen Hegelund }
58*c9da1ac1SSteen Hegelund 
59*c9da1ac1SSteen Hegelund /* Find a rule id with a provided cookie */
60*c9da1ac1SSteen Hegelund int vcap_lookup_rule_by_cookie(struct vcap_control *vctrl, u64 cookie)
61*c9da1ac1SSteen Hegelund {
62*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri;
63*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin;
64*c9da1ac1SSteen Hegelund 
65*c9da1ac1SSteen Hegelund 	/* Look for the rule id in all vcaps */
66*c9da1ac1SSteen Hegelund 	list_for_each_entry(admin, &vctrl->list, list)
67*c9da1ac1SSteen Hegelund 		list_for_each_entry(ri, &admin->rules, list)
68*c9da1ac1SSteen Hegelund 			if (ri->data.cookie == cookie)
69*c9da1ac1SSteen Hegelund 				return ri->data.id;
70*c9da1ac1SSteen Hegelund 	return -ENOENT;
71*c9da1ac1SSteen Hegelund }
72*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_lookup_rule_by_cookie);
73*c9da1ac1SSteen Hegelund 
74*c9da1ac1SSteen Hegelund /* Lookup a vcap instance using chain id */
75*c9da1ac1SSteen Hegelund struct vcap_admin *vcap_find_admin(struct vcap_control *vctrl, int cid)
76*c9da1ac1SSteen Hegelund {
77*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin;
78*c9da1ac1SSteen Hegelund 
79*c9da1ac1SSteen Hegelund 	list_for_each_entry(admin, &vctrl->list, list) {
80*c9da1ac1SSteen Hegelund 		if (cid >= admin->first_cid && cid <= admin->last_cid)
81*c9da1ac1SSteen Hegelund 			return admin;
82*c9da1ac1SSteen Hegelund 	}
83*c9da1ac1SSteen Hegelund 	return NULL;
84*c9da1ac1SSteen Hegelund }
85*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_find_admin);
86*c9da1ac1SSteen Hegelund 
87*c9da1ac1SSteen Hegelund /* Validate a rule with respect to available port keys */
88*c9da1ac1SSteen Hegelund int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto)
89*c9da1ac1SSteen Hegelund {
90*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri = to_intrule(rule);
91*c9da1ac1SSteen Hegelund 
92*c9da1ac1SSteen Hegelund 	/* This validation will be much expanded later */
93*c9da1ac1SSteen Hegelund 	if (!ri->admin) {
94*c9da1ac1SSteen Hegelund 		ri->data.exterr = VCAP_ERR_NO_ADMIN;
95*c9da1ac1SSteen Hegelund 		return -EINVAL;
96*c9da1ac1SSteen Hegelund 	}
97*c9da1ac1SSteen Hegelund 	if (!ri->ndev) {
98*c9da1ac1SSteen Hegelund 		ri->data.exterr = VCAP_ERR_NO_NETDEV;
99*c9da1ac1SSteen Hegelund 		return -EINVAL;
100*c9da1ac1SSteen Hegelund 	}
101*c9da1ac1SSteen Hegelund 	if (ri->data.keyset == VCAP_KFS_NO_VALUE) {
102*c9da1ac1SSteen Hegelund 		ri->data.exterr = VCAP_ERR_NO_KEYSET_MATCH;
103*c9da1ac1SSteen Hegelund 		return -EINVAL;
104*c9da1ac1SSteen Hegelund 	}
105*c9da1ac1SSteen Hegelund 	if (ri->data.actionset == VCAP_AFS_NO_VALUE) {
106*c9da1ac1SSteen Hegelund 		ri->data.exterr = VCAP_ERR_NO_ACTIONSET_MATCH;
107*c9da1ac1SSteen Hegelund 		return -EINVAL;
108*c9da1ac1SSteen Hegelund 	}
109*c9da1ac1SSteen Hegelund 	return 0;
110*c9da1ac1SSteen Hegelund }
111*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_val_rule);
112*c9da1ac1SSteen Hegelund 
113*c9da1ac1SSteen Hegelund /* Assign a unique rule id and autogenerate one if id == 0 */
114*c9da1ac1SSteen Hegelund static u32 vcap_set_rule_id(struct vcap_rule_internal *ri)
115*c9da1ac1SSteen Hegelund {
116*c9da1ac1SSteen Hegelund 	u32 next_id;
117*c9da1ac1SSteen Hegelund 
118*c9da1ac1SSteen Hegelund 	if (ri->data.id != 0)
119*c9da1ac1SSteen Hegelund 		return ri->data.id;
120*c9da1ac1SSteen Hegelund 
121*c9da1ac1SSteen Hegelund 	next_id = ri->vctrl->rule_id + 1;
122*c9da1ac1SSteen Hegelund 
123*c9da1ac1SSteen Hegelund 	for (next_id = ri->vctrl->rule_id + 1; next_id < ~0; ++next_id) {
124*c9da1ac1SSteen Hegelund 		if (!vcap_lookup_rule(ri->vctrl, next_id)) {
125*c9da1ac1SSteen Hegelund 			ri->data.id = next_id;
126*c9da1ac1SSteen Hegelund 			ri->vctrl->rule_id = next_id;
127*c9da1ac1SSteen Hegelund 			break;
128*c9da1ac1SSteen Hegelund 		}
129*c9da1ac1SSteen Hegelund 	}
130*c9da1ac1SSteen Hegelund 	return ri->data.id;
131*c9da1ac1SSteen Hegelund }
132*c9da1ac1SSteen Hegelund 
133*c9da1ac1SSteen Hegelund /* Encode and write a validated rule to the VCAP */
134*c9da1ac1SSteen Hegelund int vcap_add_rule(struct vcap_rule *rule)
135*c9da1ac1SSteen Hegelund {
136*c9da1ac1SSteen Hegelund 	/* This will later handling the encode and writing of the rule */
137*c9da1ac1SSteen Hegelund 	return 0;
138*c9da1ac1SSteen Hegelund }
139*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_add_rule);
140*c9da1ac1SSteen Hegelund 
141*c9da1ac1SSteen Hegelund /* Allocate a new rule with the provided arguments */
142*c9da1ac1SSteen Hegelund struct vcap_rule *vcap_alloc_rule(struct vcap_control *vctrl,
143*c9da1ac1SSteen Hegelund 				  struct net_device *ndev, int vcap_chain_id,
144*c9da1ac1SSteen Hegelund 				  enum vcap_user user, u16 priority,
145*c9da1ac1SSteen Hegelund 				  u32 id)
146*c9da1ac1SSteen Hegelund {
147*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri;
148*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin;
149*c9da1ac1SSteen Hegelund 
150*c9da1ac1SSteen Hegelund 	if (!ndev)
151*c9da1ac1SSteen Hegelund 		return ERR_PTR(-ENODEV);
152*c9da1ac1SSteen Hegelund 	/* Get the VCAP instance */
153*c9da1ac1SSteen Hegelund 	admin = vcap_find_admin(vctrl, vcap_chain_id);
154*c9da1ac1SSteen Hegelund 	if (!admin)
155*c9da1ac1SSteen Hegelund 		return ERR_PTR(-ENOENT);
156*c9da1ac1SSteen Hegelund 	/* Create a container for the rule and return it */
157*c9da1ac1SSteen Hegelund 	ri = kzalloc(sizeof(*ri), GFP_KERNEL);
158*c9da1ac1SSteen Hegelund 	if (!ri)
159*c9da1ac1SSteen Hegelund 		return ERR_PTR(-ENOMEM);
160*c9da1ac1SSteen Hegelund 	ri->data.vcap_chain_id = vcap_chain_id;
161*c9da1ac1SSteen Hegelund 	ri->data.user = user;
162*c9da1ac1SSteen Hegelund 	ri->data.priority = priority;
163*c9da1ac1SSteen Hegelund 	ri->data.id = id;
164*c9da1ac1SSteen Hegelund 	ri->data.keyset = VCAP_KFS_NO_VALUE;
165*c9da1ac1SSteen Hegelund 	ri->data.actionset = VCAP_AFS_NO_VALUE;
166*c9da1ac1SSteen Hegelund 	INIT_LIST_HEAD(&ri->list);
167*c9da1ac1SSteen Hegelund 	INIT_LIST_HEAD(&ri->data.keyfields);
168*c9da1ac1SSteen Hegelund 	INIT_LIST_HEAD(&ri->data.actionfields);
169*c9da1ac1SSteen Hegelund 	ri->ndev = ndev;
170*c9da1ac1SSteen Hegelund 	ri->admin = admin; /* refer to the vcap instance */
171*c9da1ac1SSteen Hegelund 	ri->vctrl = vctrl; /* refer to the client */
172*c9da1ac1SSteen Hegelund 	if (vcap_set_rule_id(ri) == 0)
173*c9da1ac1SSteen Hegelund 		goto out_free;
174*c9da1ac1SSteen Hegelund 	return (struct vcap_rule *)ri;
175*c9da1ac1SSteen Hegelund 
176*c9da1ac1SSteen Hegelund out_free:
177*c9da1ac1SSteen Hegelund 	kfree(ri);
178*c9da1ac1SSteen Hegelund 	return ERR_PTR(-EINVAL);
179*c9da1ac1SSteen Hegelund }
180*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_alloc_rule);
181*c9da1ac1SSteen Hegelund 
182*c9da1ac1SSteen Hegelund /* Free mem of a rule owned by client after the rule as been added to the VCAP */
183*c9da1ac1SSteen Hegelund void vcap_free_rule(struct vcap_rule *rule)
184*c9da1ac1SSteen Hegelund {
185*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri = to_intrule(rule);
186*c9da1ac1SSteen Hegelund 	struct vcap_client_actionfield *caf, *next_caf;
187*c9da1ac1SSteen Hegelund 	struct vcap_client_keyfield *ckf, *next_ckf;
188*c9da1ac1SSteen Hegelund 
189*c9da1ac1SSteen Hegelund 	/* Deallocate the list of keys and actions */
190*c9da1ac1SSteen Hegelund 	list_for_each_entry_safe(ckf, next_ckf, &ri->data.keyfields, ctrl.list) {
191*c9da1ac1SSteen Hegelund 		list_del(&ckf->ctrl.list);
192*c9da1ac1SSteen Hegelund 		kfree(ckf);
193*c9da1ac1SSteen Hegelund 	}
194*c9da1ac1SSteen Hegelund 	list_for_each_entry_safe(caf, next_caf, &ri->data.actionfields, ctrl.list) {
195*c9da1ac1SSteen Hegelund 		list_del(&caf->ctrl.list);
196*c9da1ac1SSteen Hegelund 		kfree(caf);
197*c9da1ac1SSteen Hegelund 	}
198*c9da1ac1SSteen Hegelund 	/* Deallocate the rule */
199*c9da1ac1SSteen Hegelund 	kfree(rule);
200*c9da1ac1SSteen Hegelund }
201*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_free_rule);
202*c9da1ac1SSteen Hegelund 
203*c9da1ac1SSteen Hegelund /* Delete rule in a VCAP instance */
204*c9da1ac1SSteen Hegelund int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id)
205*c9da1ac1SSteen Hegelund {
206*c9da1ac1SSteen Hegelund 	struct vcap_rule_internal *ri, *elem;
207*c9da1ac1SSteen Hegelund 	struct vcap_admin *admin;
208*c9da1ac1SSteen Hegelund 
209*c9da1ac1SSteen Hegelund 	/* This will later also handle rule moving */
210*c9da1ac1SSteen Hegelund 	if (!ndev)
211*c9da1ac1SSteen Hegelund 		return -ENODEV;
212*c9da1ac1SSteen Hegelund 	/* Look for the rule id in all vcaps */
213*c9da1ac1SSteen Hegelund 	ri = vcap_lookup_rule(vctrl, id);
214*c9da1ac1SSteen Hegelund 	if (!ri)
215*c9da1ac1SSteen Hegelund 		return -EINVAL;
216*c9da1ac1SSteen Hegelund 	admin = ri->admin;
217*c9da1ac1SSteen Hegelund 	list_del(&ri->list);
218*c9da1ac1SSteen Hegelund 	if (list_empty(&admin->rules)) {
219*c9da1ac1SSteen Hegelund 		admin->last_used_addr = admin->last_valid_addr;
220*c9da1ac1SSteen Hegelund 	} else {
221*c9da1ac1SSteen Hegelund 		/* update the address range end marker from the last rule in the list */
222*c9da1ac1SSteen Hegelund 		elem = list_last_entry(&admin->rules, struct vcap_rule_internal, list);
223*c9da1ac1SSteen Hegelund 		admin->last_used_addr = elem->addr;
224*c9da1ac1SSteen Hegelund 	}
225*c9da1ac1SSteen Hegelund 	kfree(ri);
226*c9da1ac1SSteen Hegelund 	return 0;
227*c9da1ac1SSteen Hegelund }
228*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_del_rule);
229*c9da1ac1SSteen Hegelund 
230*c9da1ac1SSteen Hegelund static void vcap_copy_from_client_keyfield(struct vcap_rule *rule,
231*c9da1ac1SSteen Hegelund 					   struct vcap_client_keyfield *field,
232*c9da1ac1SSteen Hegelund 					   struct vcap_client_keyfield_data *data)
233*c9da1ac1SSteen Hegelund {
234*c9da1ac1SSteen Hegelund 	/* This will be expanded later to handle different vcap memory layouts */
235*c9da1ac1SSteen Hegelund 	memcpy(&field->data, data, sizeof(field->data));
236*c9da1ac1SSteen Hegelund }
237*c9da1ac1SSteen Hegelund 
238*c9da1ac1SSteen Hegelund static int vcap_rule_add_key(struct vcap_rule *rule,
239*c9da1ac1SSteen Hegelund 			     enum vcap_key_field key,
240*c9da1ac1SSteen Hegelund 			     enum vcap_field_type ftype,
241*c9da1ac1SSteen Hegelund 			     struct vcap_client_keyfield_data *data)
242*c9da1ac1SSteen Hegelund {
243*c9da1ac1SSteen Hegelund 	struct vcap_client_keyfield *field;
244*c9da1ac1SSteen Hegelund 
245*c9da1ac1SSteen Hegelund 	/* More validation will be added here later */
246*c9da1ac1SSteen Hegelund 	field = kzalloc(sizeof(*field), GFP_KERNEL);
247*c9da1ac1SSteen Hegelund 	if (!field)
248*c9da1ac1SSteen Hegelund 		return -ENOMEM;
249*c9da1ac1SSteen Hegelund 	field->ctrl.key = key;
250*c9da1ac1SSteen Hegelund 	field->ctrl.type = ftype;
251*c9da1ac1SSteen Hegelund 	vcap_copy_from_client_keyfield(rule, field, data);
252*c9da1ac1SSteen Hegelund 	list_add_tail(&field->ctrl.list, &rule->keyfields);
253*c9da1ac1SSteen Hegelund 	return 0;
254*c9da1ac1SSteen Hegelund }
255*c9da1ac1SSteen Hegelund 
256*c9da1ac1SSteen Hegelund /* Add a 48 bit key with value and mask to the rule */
257*c9da1ac1SSteen Hegelund int vcap_rule_add_key_u48(struct vcap_rule *rule, enum vcap_key_field key,
258*c9da1ac1SSteen Hegelund 			  struct vcap_u48_key *fieldval)
259*c9da1ac1SSteen Hegelund {
260*c9da1ac1SSteen Hegelund 	struct vcap_client_keyfield_data data;
261*c9da1ac1SSteen Hegelund 
262*c9da1ac1SSteen Hegelund 	memcpy(&data.u48, fieldval, sizeof(data.u48));
263*c9da1ac1SSteen Hegelund 	return vcap_rule_add_key(rule, key, VCAP_FIELD_U48, &data);
264*c9da1ac1SSteen Hegelund }
265*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_rule_add_key_u48);
266*c9da1ac1SSteen Hegelund 
267*c9da1ac1SSteen Hegelund static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
268*c9da1ac1SSteen Hegelund 					      struct vcap_client_actionfield *field,
269*c9da1ac1SSteen Hegelund 					      struct vcap_client_actionfield_data *data)
270*c9da1ac1SSteen Hegelund {
271*c9da1ac1SSteen Hegelund 	/* This will be expanded later to handle different vcap memory layouts */
272*c9da1ac1SSteen Hegelund 	memcpy(&field->data, data, sizeof(field->data));
273*c9da1ac1SSteen Hegelund }
274*c9da1ac1SSteen Hegelund 
275*c9da1ac1SSteen Hegelund static int vcap_rule_add_action(struct vcap_rule *rule,
276*c9da1ac1SSteen Hegelund 				enum vcap_action_field action,
277*c9da1ac1SSteen Hegelund 				enum vcap_field_type ftype,
278*c9da1ac1SSteen Hegelund 				struct vcap_client_actionfield_data *data)
279*c9da1ac1SSteen Hegelund {
280*c9da1ac1SSteen Hegelund 	struct vcap_client_actionfield *field;
281*c9da1ac1SSteen Hegelund 
282*c9da1ac1SSteen Hegelund 	/* More validation will be added here later */
283*c9da1ac1SSteen Hegelund 	field = kzalloc(sizeof(*field), GFP_KERNEL);
284*c9da1ac1SSteen Hegelund 	if (!field)
285*c9da1ac1SSteen Hegelund 		return -ENOMEM;
286*c9da1ac1SSteen Hegelund 	field->ctrl.action = action;
287*c9da1ac1SSteen Hegelund 	field->ctrl.type = ftype;
288*c9da1ac1SSteen Hegelund 	vcap_copy_from_client_actionfield(rule, field, data);
289*c9da1ac1SSteen Hegelund 	list_add_tail(&field->ctrl.list, &rule->actionfields);
290*c9da1ac1SSteen Hegelund 	return 0;
291*c9da1ac1SSteen Hegelund }
292*c9da1ac1SSteen Hegelund 
293*c9da1ac1SSteen Hegelund static void vcap_rule_set_action_bitsize(struct vcap_u1_action *u1,
294*c9da1ac1SSteen Hegelund 					 enum vcap_bit val)
295*c9da1ac1SSteen Hegelund {
296*c9da1ac1SSteen Hegelund 	switch (val) {
297*c9da1ac1SSteen Hegelund 	case VCAP_BIT_0:
298*c9da1ac1SSteen Hegelund 		u1->value = 0;
299*c9da1ac1SSteen Hegelund 		break;
300*c9da1ac1SSteen Hegelund 	case VCAP_BIT_1:
301*c9da1ac1SSteen Hegelund 		u1->value = 1;
302*c9da1ac1SSteen Hegelund 		break;
303*c9da1ac1SSteen Hegelund 	case VCAP_BIT_ANY:
304*c9da1ac1SSteen Hegelund 		u1->value = 0;
305*c9da1ac1SSteen Hegelund 		break;
306*c9da1ac1SSteen Hegelund 	}
307*c9da1ac1SSteen Hegelund }
308*c9da1ac1SSteen Hegelund 
309*c9da1ac1SSteen Hegelund /* Add a bit action with value to the rule */
310*c9da1ac1SSteen Hegelund int vcap_rule_add_action_bit(struct vcap_rule *rule,
311*c9da1ac1SSteen Hegelund 			     enum vcap_action_field action,
312*c9da1ac1SSteen Hegelund 			     enum vcap_bit val)
313*c9da1ac1SSteen Hegelund {
314*c9da1ac1SSteen Hegelund 	struct vcap_client_actionfield_data data;
315*c9da1ac1SSteen Hegelund 
316*c9da1ac1SSteen Hegelund 	vcap_rule_set_action_bitsize(&data.u1, val);
317*c9da1ac1SSteen Hegelund 	return vcap_rule_add_action(rule, action, VCAP_FIELD_BIT, &data);
318*c9da1ac1SSteen Hegelund }
319*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_rule_add_action_bit);
320*c9da1ac1SSteen Hegelund 
321*c9da1ac1SSteen Hegelund /* Add a 32 bit action field with value to the rule */
322*c9da1ac1SSteen Hegelund int vcap_rule_add_action_u32(struct vcap_rule *rule,
323*c9da1ac1SSteen Hegelund 			     enum vcap_action_field action,
324*c9da1ac1SSteen Hegelund 			     u32 value)
325*c9da1ac1SSteen Hegelund {
326*c9da1ac1SSteen Hegelund 	struct vcap_client_actionfield_data data;
327*c9da1ac1SSteen Hegelund 
328*c9da1ac1SSteen Hegelund 	data.u32.value = value;
329*c9da1ac1SSteen Hegelund 	return vcap_rule_add_action(rule, action, VCAP_FIELD_U32, &data);
330*c9da1ac1SSteen Hegelund }
331*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_rule_add_action_u32);
332*c9da1ac1SSteen Hegelund 
333*c9da1ac1SSteen Hegelund /* Copy to host byte order */
334*c9da1ac1SSteen Hegelund void vcap_netbytes_copy(u8 *dst, u8 *src, int count)
335*c9da1ac1SSteen Hegelund {
336*c9da1ac1SSteen Hegelund 	int idx;
337*c9da1ac1SSteen Hegelund 
338*c9da1ac1SSteen Hegelund 	for (idx = 0; idx < count; ++idx, ++dst)
339*c9da1ac1SSteen Hegelund 		*dst = src[count - idx - 1];
340*c9da1ac1SSteen Hegelund }
341*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_netbytes_copy);
342*c9da1ac1SSteen Hegelund 
343*c9da1ac1SSteen Hegelund /* Convert validation error code into tc extact error message */
344*c9da1ac1SSteen Hegelund void vcap_set_tc_exterr(struct flow_cls_offload *fco, struct vcap_rule *vrule)
345*c9da1ac1SSteen Hegelund {
346*c9da1ac1SSteen Hegelund 	switch (vrule->exterr) {
347*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NONE:
348*c9da1ac1SSteen Hegelund 		break;
349*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NO_ADMIN:
350*c9da1ac1SSteen Hegelund 		NL_SET_ERR_MSG_MOD(fco->common.extack,
351*c9da1ac1SSteen Hegelund 				   "Missing VCAP instance");
352*c9da1ac1SSteen Hegelund 		break;
353*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NO_NETDEV:
354*c9da1ac1SSteen Hegelund 		NL_SET_ERR_MSG_MOD(fco->common.extack,
355*c9da1ac1SSteen Hegelund 				   "Missing network interface");
356*c9da1ac1SSteen Hegelund 		break;
357*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NO_KEYSET_MATCH:
358*c9da1ac1SSteen Hegelund 		NL_SET_ERR_MSG_MOD(fco->common.extack,
359*c9da1ac1SSteen Hegelund 				   "No keyset matched the filter keys");
360*c9da1ac1SSteen Hegelund 		break;
361*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NO_ACTIONSET_MATCH:
362*c9da1ac1SSteen Hegelund 		NL_SET_ERR_MSG_MOD(fco->common.extack,
363*c9da1ac1SSteen Hegelund 				   "No actionset matched the filter actions");
364*c9da1ac1SSteen Hegelund 		break;
365*c9da1ac1SSteen Hegelund 	case VCAP_ERR_NO_PORT_KEYSET_MATCH:
366*c9da1ac1SSteen Hegelund 		NL_SET_ERR_MSG_MOD(fco->common.extack,
367*c9da1ac1SSteen Hegelund 				   "No port keyset matched the filter keys");
368*c9da1ac1SSteen Hegelund 		break;
369*c9da1ac1SSteen Hegelund 	}
370*c9da1ac1SSteen Hegelund }
371*c9da1ac1SSteen Hegelund EXPORT_SYMBOL_GPL(vcap_set_tc_exterr);
372