@@ -28,6 +28,14 @@ struct sparx5_multiple_rules {
28
28
struct sparx5_wildcard_rule rule [SPX5_MAX_RULE_SIZE ];
29
29
};
30
30
31
+ struct sparx5_tc_flower_template {
32
+ struct list_head list ; /* for insertion in the list of templates */
33
+ int cid ; /* chain id */
34
+ enum vcap_keyfield_set orig ; /* keyset used before the template */
35
+ enum vcap_keyfield_set keyset ; /* new keyset used by template */
36
+ u16 l3_proto ; /* protocol specified in the template */
37
+ };
38
+
31
39
static int
32
40
sparx5_tc_flower_es0_tpid (struct vcap_tc_flower_parse_usage * st )
33
41
{
@@ -382,7 +390,7 @@ static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,
382
390
/* Find the keysets that the rule can use */
383
391
matches .keysets = keysets ;
384
392
matches .max = ARRAY_SIZE (keysets );
385
- if (vcap_rule_find_keysets (vrule , & matches ) == 0 )
393
+ if (! vcap_rule_find_keysets (vrule , & matches ))
386
394
return - EINVAL ;
387
395
388
396
/* Find the keysets that the port configuration supports */
@@ -996,6 +1004,73 @@ static int sparx5_tc_action_vlan_push(struct vcap_admin *admin,
996
1004
return err ;
997
1005
}
998
1006
1007
+ /* Remove rule keys that may prevent templates from matching a keyset */
1008
+ static void sparx5_tc_flower_simplify_rule (struct vcap_admin * admin ,
1009
+ struct vcap_rule * vrule ,
1010
+ u16 l3_proto )
1011
+ {
1012
+ switch (admin -> vtype ) {
1013
+ case VCAP_TYPE_IS0 :
1014
+ vcap_rule_rem_key (vrule , VCAP_KF_ETYPE );
1015
+ switch (l3_proto ) {
1016
+ case ETH_P_IP :
1017
+ break ;
1018
+ case ETH_P_IPV6 :
1019
+ vcap_rule_rem_key (vrule , VCAP_KF_IP_SNAP_IS );
1020
+ break ;
1021
+ default :
1022
+ break ;
1023
+ }
1024
+ break ;
1025
+ case VCAP_TYPE_ES2 :
1026
+ switch (l3_proto ) {
1027
+ case ETH_P_IP :
1028
+ if (vrule -> keyset == VCAP_KFS_IP4_OTHER )
1029
+ vcap_rule_rem_key (vrule , VCAP_KF_TCP_IS );
1030
+ break ;
1031
+ case ETH_P_IPV6 :
1032
+ if (vrule -> keyset == VCAP_KFS_IP6_STD )
1033
+ vcap_rule_rem_key (vrule , VCAP_KF_TCP_IS );
1034
+ vcap_rule_rem_key (vrule , VCAP_KF_IP4_IS );
1035
+ break ;
1036
+ default :
1037
+ break ;
1038
+ }
1039
+ break ;
1040
+ case VCAP_TYPE_IS2 :
1041
+ switch (l3_proto ) {
1042
+ case ETH_P_IP :
1043
+ case ETH_P_IPV6 :
1044
+ vcap_rule_rem_key (vrule , VCAP_KF_IP4_IS );
1045
+ break ;
1046
+ default :
1047
+ break ;
1048
+ }
1049
+ break ;
1050
+ default :
1051
+ break ;
1052
+ }
1053
+ }
1054
+
1055
+ static bool sparx5_tc_flower_use_template (struct net_device * ndev ,
1056
+ struct flow_cls_offload * fco ,
1057
+ struct vcap_admin * admin ,
1058
+ struct vcap_rule * vrule )
1059
+ {
1060
+ struct sparx5_port * port = netdev_priv (ndev );
1061
+ struct sparx5_tc_flower_template * ftp ;
1062
+
1063
+ list_for_each_entry (ftp , & port -> tc_templates , list ) {
1064
+ if (ftp -> cid != fco -> common .chain_index )
1065
+ continue ;
1066
+
1067
+ vcap_set_rule_set_keyset (vrule , ftp -> keyset );
1068
+ sparx5_tc_flower_simplify_rule (admin , vrule , ftp -> l3_proto );
1069
+ return true;
1070
+ }
1071
+ return false;
1072
+ }
1073
+
999
1074
static int sparx5_tc_flower_replace (struct net_device * ndev ,
1000
1075
struct flow_cls_offload * fco ,
1001
1076
struct vcap_admin * admin ,
@@ -1122,12 +1197,14 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
1122
1197
goto out ;
1123
1198
}
1124
1199
1125
- err = sparx5_tc_select_protocol_keyset (ndev , vrule , admin ,
1126
- state .l3_proto , & multi );
1127
- if (err ) {
1128
- NL_SET_ERR_MSG_MOD (fco -> common .extack ,
1129
- "No matching port keyset for filter protocol and keys" );
1130
- goto out ;
1200
+ if (!sparx5_tc_flower_use_template (ndev , fco , admin , vrule )) {
1201
+ err = sparx5_tc_select_protocol_keyset (ndev , vrule , admin ,
1202
+ state .l3_proto , & multi );
1203
+ if (err ) {
1204
+ NL_SET_ERR_MSG_MOD (fco -> common .extack ,
1205
+ "No matching port keyset for filter protocol and keys" );
1206
+ goto out ;
1207
+ }
1131
1208
}
1132
1209
1133
1210
/* provide the l3 protocol to guide the keyset selection */
@@ -1259,6 +1336,120 @@ static int sparx5_tc_flower_stats(struct net_device *ndev,
1259
1336
return err ;
1260
1337
}
1261
1338
1339
+ static int sparx5_tc_flower_template_create (struct net_device * ndev ,
1340
+ struct flow_cls_offload * fco ,
1341
+ struct vcap_admin * admin )
1342
+ {
1343
+ struct sparx5_port * port = netdev_priv (ndev );
1344
+ struct vcap_tc_flower_parse_usage state = {
1345
+ .fco = fco ,
1346
+ .l3_proto = ETH_P_ALL ,
1347
+ .admin = admin ,
1348
+ };
1349
+ struct sparx5_tc_flower_template * ftp ;
1350
+ struct vcap_keyset_list kslist = {};
1351
+ enum vcap_keyfield_set keysets [10 ];
1352
+ struct vcap_control * vctrl ;
1353
+ struct vcap_rule * vrule ;
1354
+ int count , err ;
1355
+
1356
+ if (admin -> vtype == VCAP_TYPE_ES0 ) {
1357
+ pr_err ("%s:%d: %s\n" , __func__ , __LINE__ ,
1358
+ "VCAP does not support templates" );
1359
+ return - EINVAL ;
1360
+ }
1361
+
1362
+ count = vcap_admin_rule_count (admin , fco -> common .chain_index );
1363
+ if (count > 0 ) {
1364
+ pr_err ("%s:%d: %s\n" , __func__ , __LINE__ ,
1365
+ "Filters are already present" );
1366
+ return - EBUSY ;
1367
+ }
1368
+
1369
+ ftp = kzalloc (sizeof (* ftp ), GFP_KERNEL );
1370
+ if (!ftp )
1371
+ return - ENOMEM ;
1372
+
1373
+ ftp -> cid = fco -> common .chain_index ;
1374
+ ftp -> orig = VCAP_KFS_NO_VALUE ;
1375
+ ftp -> keyset = VCAP_KFS_NO_VALUE ;
1376
+
1377
+ vctrl = port -> sparx5 -> vcap_ctrl ;
1378
+ vrule = vcap_alloc_rule (vctrl , ndev , fco -> common .chain_index ,
1379
+ VCAP_USER_TC , fco -> common .prio , 0 );
1380
+ if (IS_ERR (vrule )) {
1381
+ err = PTR_ERR (vrule );
1382
+ goto err_rule ;
1383
+ }
1384
+
1385
+ state .vrule = vrule ;
1386
+ state .frule = flow_cls_offload_flow_rule (fco );
1387
+ err = sparx5_tc_use_dissectors (& state , admin , vrule );
1388
+ if (err ) {
1389
+ pr_err ("%s:%d: key error: %d\n" , __func__ , __LINE__ , err );
1390
+ goto out ;
1391
+ }
1392
+
1393
+ ftp -> l3_proto = state .l3_proto ;
1394
+
1395
+ sparx5_tc_flower_simplify_rule (admin , vrule , state .l3_proto );
1396
+
1397
+ /* Find the keysets that the rule can use */
1398
+ kslist .keysets = keysets ;
1399
+ kslist .max = ARRAY_SIZE (keysets );
1400
+ if (!vcap_rule_find_keysets (vrule , & kslist )) {
1401
+ pr_err ("%s:%d: %s\n" , __func__ , __LINE__ ,
1402
+ "Could not find a suitable keyset" );
1403
+ err = - ENOENT ;
1404
+ goto out ;
1405
+ }
1406
+
1407
+ ftp -> keyset = vcap_select_min_rule_keyset (vctrl , admin -> vtype , & kslist );
1408
+ kslist .cnt = 0 ;
1409
+ sparx5_vcap_set_port_keyset (ndev , admin , fco -> common .chain_index ,
1410
+ state .l3_proto ,
1411
+ ftp -> keyset ,
1412
+ & kslist );
1413
+
1414
+ if (kslist .cnt > 0 )
1415
+ ftp -> orig = kslist .keysets [0 ];
1416
+
1417
+ /* Store new template */
1418
+ list_add_tail (& ftp -> list , & port -> tc_templates );
1419
+ vcap_free_rule (vrule );
1420
+ return 0 ;
1421
+
1422
+ out :
1423
+ vcap_free_rule (vrule );
1424
+ err_rule :
1425
+ kfree (ftp );
1426
+ return err ;
1427
+ }
1428
+
1429
+ static int sparx5_tc_flower_template_destroy (struct net_device * ndev ,
1430
+ struct flow_cls_offload * fco ,
1431
+ struct vcap_admin * admin )
1432
+ {
1433
+ struct sparx5_port * port = netdev_priv (ndev );
1434
+ struct sparx5_tc_flower_template * ftp , * tmp ;
1435
+ int err = - ENOENT ;
1436
+
1437
+ /* Rules using the template are removed by the tc framework */
1438
+ list_for_each_entry_safe (ftp , tmp , & port -> tc_templates , list ) {
1439
+ if (ftp -> cid != fco -> common .chain_index )
1440
+ continue ;
1441
+
1442
+ sparx5_vcap_set_port_keyset (ndev , admin ,
1443
+ fco -> common .chain_index ,
1444
+ ftp -> l3_proto , ftp -> orig ,
1445
+ NULL );
1446
+ list_del (& ftp -> list );
1447
+ kfree (ftp );
1448
+ break ;
1449
+ }
1450
+ return err ;
1451
+ }
1452
+
1262
1453
int sparx5_tc_flower (struct net_device * ndev , struct flow_cls_offload * fco ,
1263
1454
bool ingress )
1264
1455
{
@@ -1282,6 +1473,10 @@ int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
1282
1473
return sparx5_tc_flower_destroy (ndev , fco , admin );
1283
1474
case FLOW_CLS_STATS :
1284
1475
return sparx5_tc_flower_stats (ndev , fco , admin );
1476
+ case FLOW_CLS_TMPLT_CREATE :
1477
+ return sparx5_tc_flower_template_create (ndev , fco , admin );
1478
+ case FLOW_CLS_TMPLT_DESTROY :
1479
+ return sparx5_tc_flower_template_destroy (ndev , fco , admin );
1285
1480
default :
1286
1481
return - EOPNOTSUPP ;
1287
1482
}
0 commit comments