Skip to content

Commit 3aaff32

Browse files
jpirkodavem330
authored andcommitted
mlxsw: spectrum_acl: Implement TC block sharing
Benefit from the prepared TC and in-driver ACL infrastructure and introduce block sharing offload. For that, a new struct "block" is introduced in spectrum_acl in order to hold a list of specific block-port bindings. Signed-off-by: Jiri Pirko <[email protected]> Acked-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 02caf49 commit 3aaff32

File tree

4 files changed

+401
-95
lines changed

4 files changed

+401
-95
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 152 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,72 +1747,186 @@ static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
17471747
}
17481748

17491749
static int
1750-
mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_port *mlxsw_sp_port,
1751-
struct tc_cls_flower_offload *f,
1752-
bool ingress)
1750+
mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block *acl_block,
1751+
struct tc_cls_flower_offload *f)
17531752
{
1753+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_acl_block_mlxsw_sp(acl_block);
1754+
17541755
switch (f->command) {
17551756
case TC_CLSFLOWER_REPLACE:
1756-
return mlxsw_sp_flower_replace(mlxsw_sp_port, ingress, f);
1757+
return mlxsw_sp_flower_replace(mlxsw_sp, acl_block, f);
17571758
case TC_CLSFLOWER_DESTROY:
1758-
mlxsw_sp_flower_destroy(mlxsw_sp_port, ingress, f);
1759+
mlxsw_sp_flower_destroy(mlxsw_sp, acl_block, f);
17591760
return 0;
17601761
case TC_CLSFLOWER_STATS:
1761-
return mlxsw_sp_flower_stats(mlxsw_sp_port, ingress, f);
1762+
return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f);
17621763
default:
17631764
return -EOPNOTSUPP;
17641765
}
17651766
}
17661767

1767-
static int mlxsw_sp_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
1768-
void *cb_priv, bool ingress)
1768+
static int mlxsw_sp_setup_tc_block_cb_matchall(enum tc_setup_type type,
1769+
void *type_data,
1770+
void *cb_priv, bool ingress)
17691771
{
17701772
struct mlxsw_sp_port *mlxsw_sp_port = cb_priv;
17711773

1772-
if (!tc_can_offload(mlxsw_sp_port->dev))
1773-
return -EOPNOTSUPP;
1774-
17751774
switch (type) {
17761775
case TC_SETUP_CLSMATCHALL:
1776+
if (!tc_can_offload(mlxsw_sp_port->dev))
1777+
return -EOPNOTSUPP;
1778+
17771779
return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data,
17781780
ingress);
17791781
case TC_SETUP_CLSFLOWER:
1780-
return mlxsw_sp_setup_tc_cls_flower(mlxsw_sp_port, type_data,
1781-
ingress);
1782+
return 0;
17821783
default:
17831784
return -EOPNOTSUPP;
17841785
}
17851786
}
17861787

1787-
static int mlxsw_sp_setup_tc_block_cb_ig(enum tc_setup_type type,
1788-
void *type_data, void *cb_priv)
1788+
static int mlxsw_sp_setup_tc_block_cb_matchall_ig(enum tc_setup_type type,
1789+
void *type_data,
1790+
void *cb_priv)
17891791
{
1790-
return mlxsw_sp_setup_tc_block_cb(type, type_data, cb_priv, true);
1792+
return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data,
1793+
cb_priv, true);
17911794
}
17921795

1793-
static int mlxsw_sp_setup_tc_block_cb_eg(enum tc_setup_type type,
1794-
void *type_data, void *cb_priv)
1796+
static int mlxsw_sp_setup_tc_block_cb_matchall_eg(enum tc_setup_type type,
1797+
void *type_data,
1798+
void *cb_priv)
17951799
{
1796-
return mlxsw_sp_setup_tc_block_cb(type, type_data, cb_priv, false);
1800+
return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data,
1801+
cb_priv, false);
1802+
}
1803+
1804+
static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type,
1805+
void *type_data, void *cb_priv)
1806+
{
1807+
struct mlxsw_sp_acl_block *acl_block = cb_priv;
1808+
1809+
switch (type) {
1810+
case TC_SETUP_CLSMATCHALL:
1811+
return 0;
1812+
case TC_SETUP_CLSFLOWER:
1813+
if (mlxsw_sp_acl_block_disabled(acl_block))
1814+
return -EOPNOTSUPP;
1815+
1816+
return mlxsw_sp_setup_tc_cls_flower(acl_block, type_data);
1817+
default:
1818+
return -EOPNOTSUPP;
1819+
}
1820+
}
1821+
1822+
static int
1823+
mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
1824+
struct tcf_block *block, bool ingress)
1825+
{
1826+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1827+
struct mlxsw_sp_acl_block *acl_block;
1828+
struct tcf_block_cb *block_cb;
1829+
int err;
1830+
1831+
block_cb = tcf_block_cb_lookup(block, mlxsw_sp_setup_tc_block_cb_flower,
1832+
mlxsw_sp);
1833+
if (!block_cb) {
1834+
acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, block->net);
1835+
if (!acl_block)
1836+
return -ENOMEM;
1837+
block_cb = __tcf_block_cb_register(block,
1838+
mlxsw_sp_setup_tc_block_cb_flower,
1839+
mlxsw_sp, acl_block);
1840+
if (IS_ERR(block_cb)) {
1841+
err = PTR_ERR(block_cb);
1842+
goto err_cb_register;
1843+
}
1844+
} else {
1845+
acl_block = tcf_block_cb_priv(block_cb);
1846+
}
1847+
tcf_block_cb_incref(block_cb);
1848+
err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block,
1849+
mlxsw_sp_port, ingress);
1850+
if (err)
1851+
goto err_block_bind;
1852+
1853+
if (ingress)
1854+
mlxsw_sp_port->ing_acl_block = acl_block;
1855+
else
1856+
mlxsw_sp_port->eg_acl_block = acl_block;
1857+
1858+
return 0;
1859+
1860+
err_block_bind:
1861+
if (!tcf_block_cb_decref(block_cb)) {
1862+
__tcf_block_cb_unregister(block_cb);
1863+
err_cb_register:
1864+
mlxsw_sp_acl_block_destroy(acl_block);
1865+
}
1866+
return err;
1867+
}
1868+
1869+
static void
1870+
mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
1871+
struct tcf_block *block, bool ingress)
1872+
{
1873+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1874+
struct mlxsw_sp_acl_block *acl_block;
1875+
struct tcf_block_cb *block_cb;
1876+
int err;
1877+
1878+
block_cb = tcf_block_cb_lookup(block, mlxsw_sp_setup_tc_block_cb_flower,
1879+
mlxsw_sp);
1880+
if (!block_cb)
1881+
return;
1882+
1883+
if (ingress)
1884+
mlxsw_sp_port->ing_acl_block = NULL;
1885+
else
1886+
mlxsw_sp_port->eg_acl_block = NULL;
1887+
1888+
acl_block = tcf_block_cb_priv(block_cb);
1889+
err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block,
1890+
mlxsw_sp_port, ingress);
1891+
if (!err && !tcf_block_cb_decref(block_cb)) {
1892+
__tcf_block_cb_unregister(block_cb);
1893+
mlxsw_sp_acl_block_destroy(acl_block);
1894+
}
17971895
}
17981896

17991897
static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
18001898
struct tc_block_offload *f)
18011899
{
18021900
tc_setup_cb_t *cb;
1901+
bool ingress;
1902+
int err;
18031903

1804-
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
1805-
cb = mlxsw_sp_setup_tc_block_cb_ig;
1806-
else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
1807-
cb = mlxsw_sp_setup_tc_block_cb_eg;
1808-
else
1904+
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
1905+
cb = mlxsw_sp_setup_tc_block_cb_matchall_ig;
1906+
ingress = true;
1907+
} else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
1908+
cb = mlxsw_sp_setup_tc_block_cb_matchall_eg;
1909+
ingress = false;
1910+
} else {
18091911
return -EOPNOTSUPP;
1912+
}
18101913

18111914
switch (f->command) {
18121915
case TC_BLOCK_BIND:
1813-
return tcf_block_cb_register(f->block, cb, mlxsw_sp_port,
1814-
mlxsw_sp_port);
1916+
err = tcf_block_cb_register(f->block, cb, mlxsw_sp_port,
1917+
mlxsw_sp_port);
1918+
if (err)
1919+
return err;
1920+
err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port,
1921+
f->block, ingress);
1922+
if (err) {
1923+
tcf_block_cb_unregister(f->block, cb, mlxsw_sp_port);
1924+
return err;
1925+
}
1926+
return 0;
18151927
case TC_BLOCK_UNBIND:
1928+
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
1929+
f->block, ingress);
18161930
tcf_block_cb_unregister(f->block, cb, mlxsw_sp_port);
18171931
return 0;
18181932
default:
@@ -1842,10 +1956,18 @@ static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable)
18421956
{
18431957
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
18441958

1845-
if (!enable && (mlxsw_sp_port->acl_rule_count ||
1846-
!list_empty(&mlxsw_sp_port->mall_tc_list))) {
1847-
netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n");
1848-
return -EINVAL;
1959+
if (!enable) {
1960+
if (mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->ing_acl_block) ||
1961+
mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->eg_acl_block) ||
1962+
!list_empty(&mlxsw_sp_port->mall_tc_list)) {
1963+
netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n");
1964+
return -EINVAL;
1965+
}
1966+
mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->ing_acl_block);
1967+
mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->eg_acl_block);
1968+
} else {
1969+
mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->ing_acl_block);
1970+
mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->eg_acl_block);
18491971
}
18501972
return 0;
18511973
}

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ struct mlxsw_sp_port {
260260
struct list_head vlans_list;
261261
struct mlxsw_sp_qdisc *root_qdisc;
262262
unsigned acl_rule_count;
263+
struct mlxsw_sp_acl_block *ing_acl_block;
264+
struct mlxsw_sp_acl_block *eg_acl_block;
263265
};
264266

265267
static inline bool
@@ -490,17 +492,34 @@ struct mlxsw_sp_acl_ops {
490492
enum mlxsw_sp_acl_profile profile);
491493
};
492494

495+
struct mlxsw_sp_acl_block;
493496
struct mlxsw_sp_acl_ruleset;
494497

495498
/* spectrum_acl.c */
496499
struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl);
500+
struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block);
501+
unsigned int mlxsw_sp_acl_block_rule_count(struct mlxsw_sp_acl_block *block);
502+
void mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block);
503+
void mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block);
504+
bool mlxsw_sp_acl_block_disabled(struct mlxsw_sp_acl_block *block);
505+
struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp,
506+
struct net *net);
507+
void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block);
508+
int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
509+
struct mlxsw_sp_acl_block *block,
510+
struct mlxsw_sp_port *mlxsw_sp_port,
511+
bool ingress);
512+
int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
513+
struct mlxsw_sp_acl_block *block,
514+
struct mlxsw_sp_port *mlxsw_sp_port,
515+
bool ingress);
497516
struct mlxsw_sp_acl_ruleset *
498-
mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, struct net_device *dev,
499-
bool ingress, u32 chain_index,
517+
mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
518+
struct mlxsw_sp_acl_block *block, u32 chain_index,
500519
enum mlxsw_sp_acl_profile profile);
501520
struct mlxsw_sp_acl_ruleset *
502-
mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp, struct net_device *dev,
503-
bool ingress, u32 chain_index,
521+
mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
522+
struct mlxsw_sp_acl_block *block, u32 chain_index,
504523
enum mlxsw_sp_acl_profile profile);
505524
void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
506525
struct mlxsw_sp_acl_ruleset *ruleset);
@@ -567,11 +586,14 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp);
567586
extern const struct mlxsw_sp_acl_ops mlxsw_sp_acl_tcam_ops;
568587

569588
/* spectrum_flower.c */
570-
int mlxsw_sp_flower_replace(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
589+
int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp,
590+
struct mlxsw_sp_acl_block *block,
571591
struct tc_cls_flower_offload *f);
572-
void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
592+
void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
593+
struct mlxsw_sp_acl_block *block,
573594
struct tc_cls_flower_offload *f);
574-
int mlxsw_sp_flower_stats(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
595+
int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
596+
struct mlxsw_sp_acl_block *block,
575597
struct tc_cls_flower_offload *f);
576598

577599
/* spectrum_qdisc.c */

0 commit comments

Comments
 (0)