1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/delay.h>
5 #include <linux/netdevice.h>
6 #include <net/flow_offload.h>
7 #include <linux/rhashtable.h>
9 #include <asm/mach-rtl838x/mach-rtl83xx.h>
14 * Parse the flow rule for the matching conditions
16 static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv
*priv
,
17 struct flow_rule
*rule
, struct rtl83xx_flow
*flow
)
19 struct flow_dissector
*dissector
= rule
->match
.dissector
;
21 pr_debug("In %s\n", __func__
);
22 /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
23 if ((dissector
->used_keys
& BIT(FLOW_DISSECTOR_KEY_CONTROL
)) == 0 ||
24 (dissector
->used_keys
& BIT(FLOW_DISSECTOR_KEY_BASIC
)) == 0) {
25 pr_err("Cannot form TC key: used_keys = 0x%x\n", dissector
->used_keys
);
29 if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_BASIC
)) {
30 struct flow_match_basic match
;
32 pr_debug("%s: BASIC\n", __func__
);
33 flow_rule_match_basic(rule
, &match
);
34 if (match
.key
->n_proto
== htons(ETH_P_ARP
))
35 flow
->rule
.frame_type
= 0;
36 if (match
.key
->n_proto
== htons(ETH_P_IP
))
37 flow
->rule
.frame_type
= 2;
38 if (match
.key
->n_proto
== htons(ETH_P_IPV6
))
39 flow
->rule
.frame_type
= 3;
40 if ((match
.key
->n_proto
== htons(ETH_P_ARP
)) || flow
->rule
.frame_type
)
41 flow
->rule
.frame_type_m
= 3;
42 if (flow
->rule
.frame_type
>= 2) {
43 if (match
.key
->ip_proto
== IPPROTO_UDP
)
44 flow
->rule
.frame_type_l4
= 0;
45 if (match
.key
->ip_proto
== IPPROTO_TCP
)
46 flow
->rule
.frame_type_l4
= 1;
47 if (match
.key
->ip_proto
== IPPROTO_ICMP
48 || match
.key
->ip_proto
==IPPROTO_ICMPV6
)
49 flow
->rule
.frame_type_l4
= 2;
50 if (match
.key
->ip_proto
== IPPROTO_TCP
)
51 flow
->rule
.frame_type_l4
= 3;
52 if ((match
.key
->ip_proto
== IPPROTO_UDP
) || flow
->rule
.frame_type_l4
)
53 flow
->rule
.frame_type_l4_m
= 7;
57 if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_ETH_ADDRS
)) {
58 struct flow_match_eth_addrs match
;
60 pr_debug("%s: ETH_ADDR\n", __func__
);
61 flow_rule_match_eth_addrs(rule
, &match
);
62 ether_addr_copy(flow
->rule
.dmac
, match
.key
->dst
);
63 ether_addr_copy(flow
->rule
.dmac_m
, match
.mask
->dst
);
64 ether_addr_copy(flow
->rule
.smac
, match
.key
->src
);
65 ether_addr_copy(flow
->rule
.smac_m
, match
.mask
->src
);
68 if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_VLAN
)) {
69 struct flow_match_vlan match
;
71 pr_debug("%s: VLAN\n", __func__
);
72 flow_rule_match_vlan(rule
, &match
);
73 flow
->rule
.itag
= match
.key
->vlan_id
;
74 flow
->rule
.itag_m
= match
.mask
->vlan_id
;
75 // TODO: What about match.key->vlan_priority ?
78 if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_IPV4_ADDRS
)) {
79 struct flow_match_ipv4_addrs match
;
81 pr_debug("%s: IPV4\n", __func__
);
82 flow_rule_match_ipv4_addrs(rule
, &match
);
83 flow
->rule
.is_ipv6
= false;
84 flow
->rule
.dip
= match
.key
->dst
;
85 flow
->rule
.dip_m
= match
.mask
->dst
;
86 flow
->rule
.sip
= match
.key
->src
;
87 flow
->rule
.sip_m
= match
.mask
->src
;
88 } else if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_IPV6_ADDRS
)) {
89 struct flow_match_ipv6_addrs match
;
91 pr_debug("%s: IPV6\n", __func__
);
92 flow
->rule
.is_ipv6
= true;
93 flow_rule_match_ipv6_addrs(rule
, &match
);
94 flow
->rule
.dip6
= match
.key
->dst
;
95 flow
->rule
.dip6_m
= match
.mask
->dst
;
96 flow
->rule
.sip6
= match
.key
->src
;
97 flow
->rule
.sip6_m
= match
.mask
->src
;
100 if (flow_rule_match_key(rule
, FLOW_DISSECTOR_KEY_PORTS
)) {
101 struct flow_match_ports match
;
103 pr_debug("%s: PORTS\n", __func__
);
104 flow_rule_match_ports(rule
, &match
);
105 flow
->rule
.dport
= match
.key
->dst
;
106 flow
->rule
.dport_m
= match
.mask
->dst
;
107 flow
->rule
.sport
= match
.key
->src
;
108 flow
->rule
.sport_m
= match
.mask
->src
;
115 static void rtl83xx_flow_bypass_all(struct rtl83xx_flow
*flow
)
117 flow
->rule
.bypass_sel
= true;
118 flow
->rule
.bypass_all
= true;
119 flow
->rule
.bypass_igr_stp
= true;
120 flow
->rule
.bypass_ibc_sc
= true;
123 static int rtl83xx_parse_fwd(struct rtl838x_switch_priv
*priv
,
124 const struct flow_action_entry
*act
, struct rtl83xx_flow
*flow
)
126 struct net_device
*dev
= act
->dev
;
129 port
= rtl83xx_port_is_under(dev
, priv
);
131 netdev_info(dev
, "%s: not a DSA device.\n", __func__
);
135 flow
->rule
.fwd_sel
= true;
136 flow
->rule
.fwd_data
= port
;
137 pr_debug("Using port index: %d\n", port
);
138 rtl83xx_flow_bypass_all(flow
);
143 static int rtl83xx_add_flow(struct rtl838x_switch_priv
*priv
, struct flow_cls_offload
*f
,
144 struct rtl83xx_flow
*flow
)
146 struct flow_rule
*rule
= flow_cls_offload_flow_rule(f
);
147 const struct flow_action_entry
*act
;
150 pr_debug("%s\n", __func__
);
152 rtl83xx_parse_flow_rule(priv
, rule
, flow
);
154 flow_action_for_each(i
, act
, &rule
->action
) {
156 case FLOW_ACTION_DROP
:
157 pr_debug("%s: DROP\n", __func__
);
158 flow
->rule
.drop
= true;
159 rtl83xx_flow_bypass_all(flow
);
162 case FLOW_ACTION_TRAP
:
163 pr_debug("%s: TRAP\n", __func__
);
164 flow
->rule
.fwd_data
= priv
->cpu_port
;
165 flow
->rule
.fwd_act
= PIE_ACT_REDIRECT_TO_PORT
;
166 rtl83xx_flow_bypass_all(flow
);
169 case FLOW_ACTION_MANGLE
:
170 pr_err("%s: FLOW_ACTION_MANGLE not supported\n", __func__
);
173 case FLOW_ACTION_ADD
:
174 pr_err("%s: FLOW_ACTION_ADD not supported\n", __func__
);
177 case FLOW_ACTION_VLAN_PUSH
:
178 pr_debug("%s: VLAN_PUSH\n", __func__
);
179 // TODO: act->vlan.proto
180 flow
->rule
.ivid_act
= PIE_ACT_VID_ASSIGN
;
181 flow
->rule
.ivid_sel
= true;
182 flow
->rule
.ivid_data
= htons(act
->vlan
.vid
);
183 flow
->rule
.ovid_act
= PIE_ACT_VID_ASSIGN
;
184 flow
->rule
.ovid_sel
= true;
185 flow
->rule
.ovid_data
= htons(act
->vlan
.vid
);
186 flow
->rule
.fwd_mod_to_cpu
= true;
189 case FLOW_ACTION_VLAN_POP
:
190 pr_debug("%s: VLAN_POP\n", __func__
);
191 flow
->rule
.ivid_act
= PIE_ACT_VID_ASSIGN
;
192 flow
->rule
.ivid_data
= 0;
193 flow
->rule
.ivid_sel
= true;
194 flow
->rule
.ovid_act
= PIE_ACT_VID_ASSIGN
;
195 flow
->rule
.ovid_data
= 0;
196 flow
->rule
.ovid_sel
= true;
197 flow
->rule
.fwd_mod_to_cpu
= true;
200 case FLOW_ACTION_CSUM
:
201 pr_err("%s: FLOW_ACTION_CSUM not supported\n", __func__
);
204 case FLOW_ACTION_REDIRECT
:
205 pr_debug("%s: REDIRECT\n", __func__
);
206 err
= rtl83xx_parse_fwd(priv
, act
, flow
);
209 flow
->rule
.fwd_act
= PIE_ACT_REDIRECT_TO_PORT
;
212 case FLOW_ACTION_MIRRED
:
213 pr_debug("%s: MIRRED\n", __func__
);
214 err
= rtl83xx_parse_fwd(priv
, act
, flow
);
217 flow
->rule
.fwd_act
= PIE_ACT_COPY_TO_PORT
;
221 pr_err("%s: Flow action not supported: %d\n", __func__
, act
->id
);
229 static const struct rhashtable_params tc_ht_params
= {
230 .head_offset
= offsetof(struct rtl83xx_flow
, node
),
231 .key_offset
= offsetof(struct rtl83xx_flow
, cookie
),
232 .key_len
= sizeof(((struct rtl83xx_flow
*)0)->cookie
),
233 .automatic_shrinking
= true,
236 static int rtl83xx_configure_flower(struct rtl838x_switch_priv
*priv
,
237 struct flow_cls_offload
*f
)
239 struct rtl83xx_flow
*flow
;
242 pr_debug("In %s\n", __func__
);
245 pr_debug("Cookie %08lx\n", f
->cookie
);
246 flow
= rhashtable_lookup(&priv
->tc_ht
, &f
->cookie
, tc_ht_params
);
248 pr_info("%s: Got flow\n", __func__
);
257 pr_debug("%s: New flow\n", __func__
);
259 flow
= kzalloc(sizeof(*flow
), GFP_KERNEL
);
265 flow
->cookie
= f
->cookie
;
268 err
= rhashtable_insert_fast(&priv
->tc_ht
, &flow
->node
, tc_ht_params
);
270 pr_err("Could not insert add new rule\n");
274 rtl83xx_add_flow(priv
, f
, flow
); // TODO: check error
276 // Add log action to flow
277 flow
->rule
.packet_cntr
= rtl83xx_packet_cntr_alloc(priv
);
278 if (flow
->rule
.packet_cntr
>= 0) {
279 pr_debug("Using packet counter %d\n", flow
->rule
.packet_cntr
);
280 flow
->rule
.log_sel
= true;
281 flow
->rule
.log_data
= flow
->rule
.packet_cntr
;
284 err
= priv
->r
->pie_rule_add(priv
, &flow
->rule
);
290 pr_err("%s: error %d\n", __func__
, err
);
294 static int rtl83xx_delete_flower(struct rtl838x_switch_priv
*priv
,
295 struct flow_cls_offload
* cls_flower
)
297 struct rtl83xx_flow
*flow
;
299 pr_debug("In %s\n", __func__
);
301 flow
= rhashtable_lookup_fast(&priv
->tc_ht
, &cls_flower
->cookie
, tc_ht_params
);
307 priv
->r
->pie_rule_rm(priv
, &flow
->rule
);
309 rhashtable_remove_fast(&priv
->tc_ht
, &flow
->node
, tc_ht_params
);
311 kfree_rcu(flow
, rcu_head
);
317 static int rtl83xx_stats_flower(struct rtl838x_switch_priv
*priv
,
318 struct flow_cls_offload
* cls_flower
)
320 struct rtl83xx_flow
*flow
;
321 unsigned long lastused
= 0;
322 int total_packets
, new_packets
;
324 pr_debug("%s: \n", __func__
);
325 flow
= rhashtable_lookup_fast(&priv
->tc_ht
, &cls_flower
->cookie
, tc_ht_params
);
329 if (flow
->rule
.packet_cntr
>= 0) {
330 total_packets
= priv
->r
->packet_cntr_read(flow
->rule
.packet_cntr
);
331 pr_debug("Total packets: %d\n", total_packets
);
332 new_packets
= total_packets
- flow
->rule
.last_packet_cnt
;
333 flow
->rule
.last_packet_cnt
= total_packets
;
336 // TODO: We need a second PIE rule to count the bytes
337 flow_stats_update(&cls_flower
->stats
, 100 * new_packets
, new_packets
, 0, lastused
,
338 FLOW_ACTION_HW_STATS_IMMEDIATE
);
342 static int rtl83xx_setup_tc_cls_flower(struct rtl838x_switch_priv
*priv
,
343 struct flow_cls_offload
*cls_flower
)
345 pr_debug("%s: %d\n", __func__
, cls_flower
->command
);
346 switch (cls_flower
->command
) {
347 case FLOW_CLS_REPLACE
:
348 return rtl83xx_configure_flower(priv
, cls_flower
);
349 case FLOW_CLS_DESTROY
:
350 return rtl83xx_delete_flower(priv
, cls_flower
);
352 return rtl83xx_stats_flower(priv
, cls_flower
);
359 static int rtl83xx_setup_tc_block_cb(enum tc_setup_type type
, void *type_data
,
362 struct rtl838x_switch_priv
*priv
= cb_priv
;
365 case TC_SETUP_CLSFLOWER
:
366 pr_debug("%s: TC_SETUP_CLSFLOWER\n", __func__
);
367 return rtl83xx_setup_tc_cls_flower(priv
, type_data
);
373 static LIST_HEAD(rtl83xx_block_cb_list
);
375 int rtl83xx_setup_tc(struct net_device
*dev
, enum tc_setup_type type
, void *type_data
)
377 struct rtl838x_switch_priv
*priv
;
378 struct flow_block_offload
*f
= type_data
;
379 static bool first_time
= true;
382 pr_debug("%s: %d\n", __func__
, type
);
384 if(!netdev_uses_dsa(dev
)) {
385 pr_err("%s: no DSA\n", __func__
);
388 priv
= dev
->dsa_ptr
->ds
->priv
;
394 err
= rhashtable_init(&priv
->tc_ht
, &tc_ht_params
);
396 pr_err("%s: Could not initialize hash table\n", __func__
);
399 f
->unlocked_driver_cb
= true;
400 return flow_block_cb_setup_simple(type_data
,
401 &rtl83xx_block_cb_list
,
402 rtl83xx_setup_tc_block_cb
,