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