Skip to content

Commit 47327e1

Browse files
Volodymyr Mytnykdavem330
authored andcommitted
net: prestera: acl: migrate to new vTCAM api
- Add new vTCAM HW API to configure HW ACLs. - Migrate acl to use new vTCAM HW API. - No counter support in this patch-set. Co-developed-by: Yevhen Orlov <[email protected]> Signed-off-by: Yevhen Orlov <[email protected]> Signed-off-by: Volodymyr Mytnyk <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4c897cf commit 47327e1

File tree

9 files changed

+985
-662
lines changed

9 files changed

+985
-662
lines changed

drivers/net/ethernet/marvell/prestera/prestera_acl.c

Lines changed: 457 additions & 183 deletions
Large diffs are not rendered by default.
Lines changed: 117 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,118 @@
11
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
2-
/* Copyright (c) 2020 Marvell International Ltd. All rights reserved. */
2+
/* Copyright (c) 2020-2021 Marvell International Ltd. All rights reserved. */
33

44
#ifndef _PRESTERA_ACL_H_
55
#define _PRESTERA_ACL_H_
66

7-
enum prestera_acl_rule_match_entry_type {
8-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_TYPE = 1,
9-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_DMAC,
10-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ETH_SMAC,
11-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_PROTO,
12-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_PORT,
13-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_SRC,
14-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_IP_DST,
15-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_SRC,
16-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_DST,
17-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_RANGE_SRC,
18-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_L4_PORT_RANGE_DST,
19-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_VLAN_ID,
20-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_VLAN_TPID,
21-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ICMP_TYPE,
22-
PRESTERA_ACL_RULE_MATCH_ENTRY_TYPE_ICMP_CODE
7+
#include <linux/types.h>
8+
9+
#define PRESTERA_ACL_KEYMASK_PCL_ID 0x3FF
10+
#define PRESTERA_ACL_KEYMASK_PCL_ID_USER \
11+
(PRESTERA_ACL_KEYMASK_PCL_ID & 0x00FF)
12+
13+
#define rule_match_set_n(match_p, type, val_p, size) \
14+
memcpy(&(match_p)[PRESTERA_ACL_RULE_MATCH_TYPE_##type], \
15+
val_p, size)
16+
#define rule_match_set(match_p, type, val) \
17+
memcpy(&(match_p)[PRESTERA_ACL_RULE_MATCH_TYPE_##type], \
18+
&(val), sizeof(val))
19+
20+
enum prestera_acl_match_type {
21+
PRESTERA_ACL_RULE_MATCH_TYPE_PCL_ID,
22+
PRESTERA_ACL_RULE_MATCH_TYPE_ETH_TYPE,
23+
PRESTERA_ACL_RULE_MATCH_TYPE_ETH_DMAC_0,
24+
PRESTERA_ACL_RULE_MATCH_TYPE_ETH_DMAC_1,
25+
PRESTERA_ACL_RULE_MATCH_TYPE_ETH_SMAC_0,
26+
PRESTERA_ACL_RULE_MATCH_TYPE_ETH_SMAC_1,
27+
PRESTERA_ACL_RULE_MATCH_TYPE_IP_PROTO,
28+
PRESTERA_ACL_RULE_MATCH_TYPE_SYS_PORT,
29+
PRESTERA_ACL_RULE_MATCH_TYPE_SYS_DEV,
30+
PRESTERA_ACL_RULE_MATCH_TYPE_IP_SRC,
31+
PRESTERA_ACL_RULE_MATCH_TYPE_IP_DST,
32+
PRESTERA_ACL_RULE_MATCH_TYPE_L4_PORT_SRC,
33+
PRESTERA_ACL_RULE_MATCH_TYPE_L4_PORT_DST,
34+
PRESTERA_ACL_RULE_MATCH_TYPE_L4_PORT_RANGE_SRC,
35+
PRESTERA_ACL_RULE_MATCH_TYPE_L4_PORT_RANGE_DST,
36+
PRESTERA_ACL_RULE_MATCH_TYPE_VLAN_ID,
37+
PRESTERA_ACL_RULE_MATCH_TYPE_VLAN_TPID,
38+
PRESTERA_ACL_RULE_MATCH_TYPE_ICMP_TYPE,
39+
PRESTERA_ACL_RULE_MATCH_TYPE_ICMP_CODE,
40+
41+
__PRESTERA_ACL_RULE_MATCH_TYPE_MAX
2342
};
2443

2544
enum prestera_acl_rule_action {
26-
PRESTERA_ACL_RULE_ACTION_ACCEPT,
27-
PRESTERA_ACL_RULE_ACTION_DROP,
28-
PRESTERA_ACL_RULE_ACTION_TRAP
45+
PRESTERA_ACL_RULE_ACTION_ACCEPT = 0,
46+
PRESTERA_ACL_RULE_ACTION_DROP = 1,
47+
PRESTERA_ACL_RULE_ACTION_TRAP = 2,
48+
PRESTERA_ACL_RULE_ACTION_COUNT = 7,
49+
50+
PRESTERA_ACL_RULE_ACTION_MAX
2951
};
3052

31-
struct prestera_switch;
32-
struct prestera_port;
33-
struct prestera_acl_rule;
34-
struct prestera_acl_ruleset;
53+
enum {
54+
PRESTERA_ACL_IFACE_TYPE_PORT,
55+
PRESTERA_ACL_IFACE_TYPE_INDEX
56+
};
3557

36-
struct prestera_flow_block_binding {
37-
struct list_head list;
38-
struct prestera_port *port;
39-
int span_id;
58+
struct prestera_acl_match {
59+
__be32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
60+
__be32 mask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
4061
};
4162

42-
struct prestera_flow_block {
43-
struct list_head binding_list;
44-
struct prestera_switch *sw;
45-
struct net *net;
46-
struct prestera_acl_ruleset *ruleset;
47-
struct flow_block_cb *block_cb;
63+
struct prestera_acl_rule_entry_key {
64+
u32 prio;
65+
struct prestera_acl_match match;
4866
};
4967

50-
struct prestera_acl_rule_action_entry {
51-
struct list_head list;
68+
struct prestera_acl_hw_action_info {
5269
enum prestera_acl_rule_action id;
5370
};
5471

55-
struct prestera_acl_rule_match_entry {
72+
/* This struct (arg) used only to be passed as parameter for
73+
* acl_rule_entry_create. Must be flat. Can contain object keys, which will be
74+
* resolved to object links, before saving to acl_rule_entry struct
75+
*/
76+
struct prestera_acl_rule_entry_arg {
77+
u32 vtcam_id;
78+
struct {
79+
struct {
80+
u8 valid:1;
81+
} accept, drop, trap;
82+
};
83+
};
84+
85+
struct prestera_acl_rule {
86+
struct rhash_head ht_node; /* Member of acl HT */
5687
struct list_head list;
57-
enum prestera_acl_rule_match_entry_type type;
88+
struct prestera_acl_ruleset *ruleset;
89+
unsigned long cookie;
90+
u32 priority;
91+
struct prestera_acl_rule_entry_key re_key;
92+
struct prestera_acl_rule_entry_arg re_arg;
93+
struct prestera_acl_rule_entry *re;
94+
};
95+
96+
struct prestera_acl_iface {
5897
union {
59-
struct {
60-
u8 key;
61-
u8 mask;
62-
} u8;
63-
struct {
64-
u16 key;
65-
u16 mask;
66-
} u16;
67-
struct {
68-
u32 key;
69-
u32 mask;
70-
} u32;
71-
struct {
72-
u64 key;
73-
u64 mask;
74-
} u64;
75-
struct {
76-
u8 key[ETH_ALEN];
77-
u8 mask[ETH_ALEN];
78-
} mac;
79-
} keymask;
98+
struct prestera_port *port;
99+
u32 index;
100+
};
101+
u8 type;
80102
};
81103

104+
struct prestera_acl;
105+
struct prestera_switch;
106+
struct prestera_flow_block;
107+
82108
int prestera_acl_init(struct prestera_switch *sw);
83109
void prestera_acl_fini(struct prestera_switch *sw);
84-
struct prestera_flow_block *
85-
prestera_acl_block_create(struct prestera_switch *sw, struct net *net);
86-
void prestera_acl_block_destroy(struct prestera_flow_block *block);
87-
struct net *prestera_acl_block_net(struct prestera_flow_block *block);
88-
struct prestera_switch *prestera_acl_block_sw(struct prestera_flow_block *block);
89-
int prestera_acl_block_bind(struct prestera_flow_block *block,
90-
struct prestera_port *port);
91-
int prestera_acl_block_unbind(struct prestera_flow_block *block,
92-
struct prestera_port *port);
93-
struct prestera_acl_ruleset *
94-
prestera_acl_block_ruleset_get(struct prestera_flow_block *block);
110+
95111
struct prestera_acl_rule *
96-
prestera_acl_rule_create(struct prestera_flow_block *block,
112+
prestera_acl_rule_create(struct prestera_acl_ruleset *ruleset,
97113
unsigned long cookie);
98-
u32 prestera_acl_rule_priority_get(struct prestera_acl_rule *rule);
99114
void prestera_acl_rule_priority_set(struct prestera_acl_rule *rule,
100115
u32 priority);
101-
u16 prestera_acl_rule_ruleset_id_get(const struct prestera_acl_rule *rule);
102-
struct list_head *
103-
prestera_acl_rule_action_list_get(struct prestera_acl_rule *rule);
104-
u8 prestera_acl_rule_action_len(struct prestera_acl_rule *rule);
105-
u8 prestera_acl_rule_match_len(struct prestera_acl_rule *rule);
106-
int prestera_acl_rule_action_add(struct prestera_acl_rule *rule,
107-
struct prestera_acl_rule_action_entry *entry);
108-
struct list_head *
109-
prestera_acl_rule_match_list_get(struct prestera_acl_rule *rule);
110-
int prestera_acl_rule_match_add(struct prestera_acl_rule *rule,
111-
struct prestera_acl_rule_match_entry *entry);
112116
void prestera_acl_rule_destroy(struct prestera_acl_rule *rule);
113117
struct prestera_acl_rule *
114118
prestera_acl_rule_lookup(struct prestera_acl_ruleset *ruleset,
@@ -117,8 +121,37 @@ int prestera_acl_rule_add(struct prestera_switch *sw,
117121
struct prestera_acl_rule *rule);
118122
void prestera_acl_rule_del(struct prestera_switch *sw,
119123
struct prestera_acl_rule *rule);
120-
int prestera_acl_rule_get_stats(struct prestera_switch *sw,
124+
int prestera_acl_rule_get_stats(struct prestera_acl *acl,
121125
struct prestera_acl_rule *rule,
122126
u64 *packets, u64 *bytes, u64 *last_use);
127+
struct prestera_acl_rule_entry *
128+
prestera_acl_rule_entry_find(struct prestera_acl *acl,
129+
struct prestera_acl_rule_entry_key *key);
130+
void prestera_acl_rule_entry_destroy(struct prestera_acl *acl,
131+
struct prestera_acl_rule_entry *e);
132+
struct prestera_acl_rule_entry *
133+
prestera_acl_rule_entry_create(struct prestera_acl *acl,
134+
struct prestera_acl_rule_entry_key *key,
135+
struct prestera_acl_rule_entry_arg *arg);
136+
struct prestera_acl_ruleset *
137+
prestera_acl_ruleset_get(struct prestera_acl *acl,
138+
struct prestera_flow_block *block);
139+
struct prestera_acl_ruleset *
140+
prestera_acl_ruleset_lookup(struct prestera_acl *acl,
141+
struct prestera_flow_block *block);
142+
bool prestera_acl_ruleset_is_offload(struct prestera_acl_ruleset *ruleset);
143+
int prestera_acl_ruleset_offload(struct prestera_acl_ruleset *ruleset);
144+
void prestera_acl_ruleset_put(struct prestera_acl_ruleset *ruleset);
145+
int prestera_acl_ruleset_bind(struct prestera_acl_ruleset *ruleset,
146+
struct prestera_port *port);
147+
int prestera_acl_ruleset_unbind(struct prestera_acl_ruleset *ruleset,
148+
struct prestera_port *port);
149+
void
150+
prestera_acl_rule_keymask_pcl_id_set(struct prestera_acl_rule *rule,
151+
u16 pcl_id);
152+
153+
int prestera_acl_vtcam_id_get(struct prestera_acl *acl, u8 lookup,
154+
void *keymask, u32 *vtcam_id);
155+
int prestera_acl_vtcam_id_put(struct prestera_acl *acl, u32 vtcam_id);
123156

124157
#endif /* _PRESTERA_ACL_H_ */

drivers/net/ethernet/marvell/prestera/prestera_flow.c

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,100 @@ static int prestera_flow_block_cb(enum tc_setup_type type,
6060
}
6161
}
6262

63+
static void prestera_flow_block_destroy(void *cb_priv)
64+
{
65+
struct prestera_flow_block *block = cb_priv;
66+
67+
WARN_ON(!list_empty(&block->binding_list));
68+
69+
kfree(block);
70+
}
71+
72+
static struct prestera_flow_block *
73+
prestera_flow_block_create(struct prestera_switch *sw, struct net *net)
74+
{
75+
struct prestera_flow_block *block;
76+
77+
block = kzalloc(sizeof(*block), GFP_KERNEL);
78+
if (!block)
79+
return NULL;
80+
81+
INIT_LIST_HEAD(&block->binding_list);
82+
block->net = net;
83+
block->sw = sw;
84+
85+
return block;
86+
}
87+
6388
static void prestera_flow_block_release(void *cb_priv)
6489
{
6590
struct prestera_flow_block *block = cb_priv;
6691

67-
prestera_acl_block_destroy(block);
92+
prestera_flow_block_destroy(block);
93+
}
94+
95+
static bool
96+
prestera_flow_block_is_bound(const struct prestera_flow_block *block)
97+
{
98+
return block->ruleset_zero;
99+
}
100+
101+
static struct prestera_flow_block_binding *
102+
prestera_flow_block_lookup(struct prestera_flow_block *block,
103+
struct prestera_port *port)
104+
{
105+
struct prestera_flow_block_binding *binding;
106+
107+
list_for_each_entry(binding, &block->binding_list, list)
108+
if (binding->port == port)
109+
return binding;
110+
111+
return NULL;
112+
}
113+
114+
static int prestera_flow_block_bind(struct prestera_flow_block *block,
115+
struct prestera_port *port)
116+
{
117+
struct prestera_flow_block_binding *binding;
118+
int err;
119+
120+
binding = kzalloc(sizeof(*binding), GFP_KERNEL);
121+
if (!binding)
122+
return -ENOMEM;
123+
124+
binding->span_id = PRESTERA_SPAN_INVALID_ID;
125+
binding->port = port;
126+
127+
if (prestera_flow_block_is_bound(block)) {
128+
err = prestera_acl_ruleset_bind(block->ruleset_zero, port);
129+
if (err)
130+
goto err_ruleset_bind;
131+
}
132+
133+
list_add(&binding->list, &block->binding_list);
134+
return 0;
135+
136+
err_ruleset_bind:
137+
kfree(binding);
138+
return err;
139+
}
140+
141+
static int prestera_flow_block_unbind(struct prestera_flow_block *block,
142+
struct prestera_port *port)
143+
{
144+
struct prestera_flow_block_binding *binding;
145+
146+
binding = prestera_flow_block_lookup(block, port);
147+
if (!binding)
148+
return -ENOENT;
149+
150+
list_del(&binding->list);
151+
152+
if (prestera_flow_block_is_bound(block))
153+
prestera_acl_ruleset_unbind(block->ruleset_zero, port);
154+
155+
kfree(binding);
156+
return 0;
68157
}
69158

70159
static struct prestera_flow_block *
@@ -78,15 +167,15 @@ prestera_flow_block_get(struct prestera_switch *sw,
78167
block_cb = flow_block_cb_lookup(f->block,
79168
prestera_flow_block_cb, sw);
80169
if (!block_cb) {
81-
block = prestera_acl_block_create(sw, f->net);
170+
block = prestera_flow_block_create(sw, f->net);
82171
if (!block)
83172
return ERR_PTR(-ENOMEM);
84173

85174
block_cb = flow_block_cb_alloc(prestera_flow_block_cb,
86175
sw, block,
87176
prestera_flow_block_release);
88177
if (IS_ERR(block_cb)) {
89-
prestera_acl_block_destroy(block);
178+
prestera_flow_block_destroy(block);
90179
return ERR_CAST(block_cb);
91180
}
92181

@@ -110,7 +199,7 @@ static void prestera_flow_block_put(struct prestera_flow_block *block)
110199
return;
111200

112201
flow_block_cb_free(block_cb);
113-
prestera_acl_block_destroy(block);
202+
prestera_flow_block_destroy(block);
114203
}
115204

116205
static int prestera_setup_flow_block_bind(struct prestera_port *port,
@@ -128,7 +217,7 @@ static int prestera_setup_flow_block_bind(struct prestera_port *port,
128217

129218
block_cb = block->block_cb;
130219

131-
err = prestera_acl_block_bind(block, port);
220+
err = prestera_flow_block_bind(block, port);
132221
if (err)
133222
goto err_block_bind;
134223

@@ -162,7 +251,7 @@ static void prestera_setup_flow_block_unbind(struct prestera_port *port,
162251

163252
prestera_span_destroy(block);
164253

165-
err = prestera_acl_block_unbind(block, port);
254+
err = prestera_flow_block_unbind(block, port);
166255
if (err)
167256
goto error;
168257

0 commit comments

Comments
 (0)