| @@ -37,6 +37,7 @@ · 36 unmodified lines |
| 37 | #include <linux/mlx5/fs.h> | 37 | #include <linux/mlx5/fs.h> |
| 38 | #include "mlx5_core.h" | 38 | #include "mlx5_core.h" |
| 39 | #include "eswitch.h" | 39 | #include "eswitch.h" |
| | 40 | #include "fs_core.h" |
| 40 | | 41 | |
| 41 | #define UPLINK_VPORT 0xFFFF | 42 | #define UPLINK_VPORT 0xFFFF |
| 42 | | 43 | |
| @@ -1123,8 +1124,12 @@ static void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw, · 1080 unmodified lines |
| 1123 | static int esw_vport_ingress_config(struct mlx5_eswitch *esw, | 1124 | static int esw_vport_ingress_config(struct mlx5_eswitch *esw, |
| 1124 | struct mlx5_vport *vport) | 1125 | struct mlx5_vport *vport) |
| 1125 | { | 1126 | { |
| | 1127 | struct mlx5_fc *counter = vport->ingress.drop_counter; |
| | 1128 | struct mlx5_flow_destination drop_ctr_dst = {0}; |
| | 1129 | struct mlx5_flow_destination *dst = NULL; |
| 1126 | struct mlx5_flow_act flow_act = {0}; | 1130 | struct mlx5_flow_act flow_act = {0}; |
| 1127 | struct mlx5_flow_spec *spec; | 1131 | struct mlx5_flow_spec *spec; |
| | 1132 | int dest_num = 0; |
| 1128 | int err = 0; | 1133 | int err = 0; |
| 1129 | u8 *smac_v; | 1134 | u8 *smac_v; |
| 1130 | | 1135 | |
| @@ -1188,9 +1193,18 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, · 57 unmodified lines |
| 1188 | | 1193 | |
| 1189 | memset(spec, 0, sizeof(*spec)); | 1194 | memset(spec, 0, sizeof(*spec)); |
| 1190 | flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; | 1195 | flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; |
| | 1196 | |
| | 1197 | /* Attach drop flow counter */ |
| | 1198 | if (counter) { |
| | 1199 | flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; |
| | 1200 | drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; |
| | 1201 | drop_ctr_dst.counter = counter; |
| | 1202 | dst = &drop_ctr_dst; |
| | 1203 | dest_num++; |
| | 1204 | } |
| 1191 | vport->ingress.drop_rule = | 1205 | vport->ingress.drop_rule = |
| 1192 | mlx5_add_flow_rules(vport->ingress.acl, spec, | 1206 | mlx5_add_flow_rules(vport->ingress.acl, spec, |
| 1193 | &flow_act, NULL, 0); | 1207 | &flow_act, dst, dest_num); |
| 1194 | if (IS_ERR(vport->ingress.drop_rule)) { | 1208 | if (IS_ERR(vport->ingress.drop_rule)) { |
| 1195 | err = PTR_ERR(vport->ingress.drop_rule); | 1209 | err = PTR_ERR(vport->ingress.drop_rule); |
| 1196 | esw_warn(esw->dev, | 1210 | esw_warn(esw->dev, |
| @@ -1210,8 +1224,12 @@ out: · 13 unmodified lines |
| 1210 | static int esw_vport_egress_config(struct mlx5_eswitch *esw, | 1224 | static int esw_vport_egress_config(struct mlx5_eswitch *esw, |
| 1211 | struct mlx5_vport *vport) | 1225 | struct mlx5_vport *vport) |
| 1212 | { | 1226 | { |
| | 1227 | struct mlx5_fc *counter = vport->egress.drop_counter; |
| | 1228 | struct mlx5_flow_destination drop_ctr_dst = {0}; |
| | 1229 | struct mlx5_flow_destination *dst = NULL; |
| 1213 | struct mlx5_flow_act flow_act = {0}; | 1230 | struct mlx5_flow_act flow_act = {0}; |
| 1214 | struct mlx5_flow_spec *spec; | 1231 | struct mlx5_flow_spec *spec; |
| | 1232 | int dest_num = 0; |
| 1215 | int err = 0; | 1233 | int err = 0; |
| 1216 | | 1234 | |
| 1217 | esw_vport_cleanup_egress_rules(esw, vport); | 1235 | esw_vport_cleanup_egress_rules(esw, vport); |
| @@ -1262,9 +1280,18 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, · 44 unmodified lines |
| 1262 | /* Drop others rule (star rule) */ | 1280 | /* Drop others rule (star rule) */ |
| 1263 | memset(spec, 0, sizeof(*spec)); | 1281 | memset(spec, 0, sizeof(*spec)); |
| 1264 | flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; | 1282 | flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; |
| | 1283 | |
| | 1284 | /* Attach egress drop flow counter */ |
| | 1285 | if (counter) { |
| | 1286 | flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; |
| | 1287 | drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; |
| | 1288 | drop_ctr_dst.counter = counter; |
| | 1289 | dst = &drop_ctr_dst; |
| | 1290 | dest_num++; |
| | 1291 | } |
| 1265 | vport->egress.drop_rule = | 1292 | vport->egress.drop_rule = |
| 1266 | mlx5_add_flow_rules(vport->egress.acl, spec, | 1293 | mlx5_add_flow_rules(vport->egress.acl, spec, |
| 1267 | &flow_act, NULL, 0); | 1294 | &flow_act, dst, dest_num); |
| 1268 | if (IS_ERR(vport->egress.drop_rule)) { | 1295 | if (IS_ERR(vport->egress.drop_rule)) { |
| 1269 | err = PTR_ERR(vport->egress.drop_rule); | 1296 | err = PTR_ERR(vport->egress.drop_rule); |
| 1270 | esw_warn(esw->dev, | 1297 | esw_warn(esw->dev, |
| @@ -1457,6 +1484,41 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw, · 186 unmodified lines |
| 1457 | } | 1484 | } |
| 1458 | } | 1485 | } |
| 1459 | | 1486 | |
| | 1487 | static void esw_vport_create_drop_counters(struct mlx5_vport *vport) |
| | 1488 | { |
| | 1489 | struct mlx5_core_dev *dev = vport->dev; |
| | 1490 | |
| | 1491 | if (MLX5_CAP_ESW_INGRESS_ACL(dev, flow_counter)) { |
| | 1492 | vport->ingress.drop_counter = mlx5_fc_create(dev, false); |
| | 1493 | if (IS_ERR(vport->ingress.drop_counter)) { |
| | 1494 | esw_warn(dev, |
| | 1495 | "vport[%d] configure ingress drop rule counter failed\n", |
| | 1496 | vport->vport); |
| | 1497 | vport->ingress.drop_counter = NULL; |
| | 1498 | } |
| | 1499 | } |
| | 1500 | |
| | 1501 | if (MLX5_CAP_ESW_EGRESS_ACL(dev, flow_counter)) { |
| | 1502 | vport->egress.drop_counter = mlx5_fc_create(dev, false); |
| | 1503 | if (IS_ERR(vport->egress.drop_counter)) { |
| | 1504 | esw_warn(dev, |
| | 1505 | "vport[%d] configure egress drop rule counter failed\n", |
| | 1506 | vport->vport); |
| | 1507 | vport->egress.drop_counter = NULL; |
| | 1508 | } |
| | 1509 | } |
| | 1510 | } |
| | 1511 | |
| | 1512 | static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport) |
| | 1513 | { |
| | 1514 | struct mlx5_core_dev *dev = vport->dev; |
| | 1515 | |
| | 1516 | if (vport->ingress.drop_counter) |
| | 1517 | mlx5_fc_destroy(dev, vport->ingress.drop_counter); |
| | 1518 | if (vport->egress.drop_counter) |
| | 1519 | mlx5_fc_destroy(dev, vport->egress.drop_counter); |
| | 1520 | } |
| | 1521 | |
| 1460 | static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, | 1522 | static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, |
| 1461 | int enable_events) | 1523 | int enable_events) |
| 1462 | { | 1524 | { |
| @@ -1483,6 +1545,10 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, · 20 unmodified lines |
| 1483 | if (!vport_num) | 1545 | if (!vport_num) |
| 1484 | vport->info.trusted = true; | 1546 | vport->info.trusted = true; |
| 1485 | | 1547 | |
| | 1548 | /* create steering drop counters for ingress and egress ACLs */ |
| | 1549 | if (vport_num && esw->mode == SRIOV_LEGACY) |
| | 1550 | esw_vport_create_drop_counters(vport); |
| | 1551 | |
| 1486 | esw_vport_change_handle_locked(vport); | 1552 | esw_vport_change_handle_locked(vport); |
| 1487 | | 1553 | |
| 1488 | esw->enabled_vports++; | 1554 | esw->enabled_vports++; |
| @@ -1521,6 +1587,7 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) · 32 unmodified lines |
| 1521 | MLX5_ESW_VPORT_ADMIN_STATE_DOWN); | 1587 | MLX5_ESW_VPORT_ADMIN_STATE_DOWN); |
| 1522 | esw_vport_disable_egress_acl(esw, vport); | 1588 | esw_vport_disable_egress_acl(esw, vport); |
| 1523 | esw_vport_disable_ingress_acl(esw, vport); | 1589 | esw_vport_disable_ingress_acl(esw, vport); |
| | 1590 | esw_vport_destroy_drop_counters(vport); |
| 1524 | } | 1591 | } |
| 1525 | esw->enabled_vports--; | 1592 | esw->enabled_vports--; |
| 1526 | mutex_unlock(&esw->state_lock); | 1593 | mutex_unlock(&esw->state_lock); |
| @@ -2016,12 +2083,36 @@ unlock: · 489 unmodified lines |
| 2016 | return err; | 2083 | return err; |
| 2017 | } | 2084 | } |
| 2018 | | 2085 | |
| | 2086 | static void mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev, |
| | 2087 | int vport_idx, |
| | 2088 | struct mlx5_vport_drop_stats *stats) |
| | 2089 | { |
| | 2090 | struct mlx5_eswitch *esw = dev->priv.eswitch; |
| | 2091 | struct mlx5_vport *vport = &esw->vports[vport_idx]; |
| | 2092 | u64 bytes = 0; |
| | 2093 | u16 idx = 0; |
| | 2094 | |
| | 2095 | if (!vport->enabled || esw->mode != SRIOV_LEGACY) |
| | 2096 | return; |
| | 2097 | |
| | 2098 | if (vport->egress.drop_counter) { |
| | 2099 | idx = vport->egress.drop_counter->id; |
| | 2100 | mlx5_fc_query(dev, idx, &stats->rx_dropped, &bytes); |
| | 2101 | } |
| | 2102 | |
| | 2103 | if (vport->ingress.drop_counter) { |
| | 2104 | idx = vport->ingress.drop_counter->id; |
| | 2105 | mlx5_fc_query(dev, idx, &stats->tx_dropped, &bytes); |
| | 2106 | } |
| | 2107 | } |
| | 2108 | |
| 2019 | int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, | 2109 | int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, |
| 2020 | int vport, | 2110 | int vport, |
| 2021 | struct ifla_vf_stats *vf_stats) | 2111 | struct ifla_vf_stats *vf_stats) |
| 2022 | { | 2112 | { |
| 2023 | int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); | 2113 | int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); |
| 2024 | u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {0}; | 2114 | u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {0}; |
| | 2115 | struct mlx5_vport_drop_stats stats = {0}; |
| 2025 | int err = 0; | 2116 | int err = 0; |
| 2026 | u32 *out; | 2117 | u32 *out; |
| 2027 | | 2118 | |
| @@ -2076,6 +2167,10 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, · 48 unmodified lines |
| 2076 | vf_stats->broadcast = | 2167 | vf_stats->broadcast = |
| 2077 | MLX5_GET_CTR(out, received_eth_broadcast.packets); | 2168 | MLX5_GET_CTR(out, received_eth_broadcast.packets); |
| 2078 | | 2169 | |
| | 2170 | mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats); |
| | 2171 | vf_stats->rx_dropped = stats.rx_dropped; |
| | 2172 | vf_stats->tx_dropped = stats.tx_dropped; |
| | 2173 | |
| 2079 | free_out: | 2174 | free_out: |
| 2080 | kvfree(out); | 2175 | kvfree(out); |
| 2081 | return err; | 2176 | return err; |