u64 rate;
int i;
- if (!flow_offload_has_one_action(&f->rule->action))
- return -EOPNOTSUPP;
-
if (!flow_action_basic_hw_stats_check(&f->rule->action,
f->common.extack))
return -EOPNOTSUPP;
flow_action_for_each(i, a, &f->rule->action) {
switch (a->id) {
case FLOW_ACTION_DROP:
- filter->action = OCELOT_VCAP_ACTION_DROP;
+ filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
+ filter->action.port_mask = 0;
+ filter->action.police_ena = true;
+ filter->action.pol_ix = OCELOT_POLICER_DISCARD;
break;
case FLOW_ACTION_TRAP:
- filter->action = OCELOT_VCAP_ACTION_TRAP;
+ filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
+ filter->action.port_mask = 0;
+ filter->action.cpu_copy_ena = true;
+ filter->action.cpu_qu_num = 0;
break;
case FLOW_ACTION_POLICE:
- filter->action = OCELOT_VCAP_ACTION_POLICE;
+ filter->action.police_ena = true;
rate = a->police.rate_bytes_ps;
- filter->pol.rate = div_u64(rate, 1000) * 8;
- filter->pol.burst = a->police.burst;
+ filter->action.pol.rate = div_u64(rate, 1000) * 8;
+ filter->action.pol.burst = a->police.burst;
break;
default:
return -EOPNOTSUPP;
#include "ocelot_police.h"
#include "ocelot_vcap.h"
-#define OCELOT_POLICER_DISCARD 0x17f
#define ENTRY_WIDTH 32
enum vcap_sel {
struct ocelot_vcap_filter *filter)
{
const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
-
- switch (filter->action) {
- case OCELOT_VCAP_ACTION_DROP:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
- OCELOT_POLICER_DISCARD);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
- break;
- case OCELOT_VCAP_ACTION_TRAP:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1);
- break;
- case OCELOT_VCAP_ACTION_POLICE:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
- filter->pol_ix);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
- break;
- }
+ struct ocelot_vcap_action *a = &filter->action;
+
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, a->mask_mode);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, a->port_mask);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, a->police_ena);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, a->pol_ix);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, a->cpu_qu_num);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, a->cpu_copy_ena);
}
static void is2_entry_set(struct ocelot *ocelot, int ix,
list_for_each_entry(filter, &block->rules, list) {
index++;
- if (filter->action == OCELOT_VCAP_ACTION_POLICE &&
- filter->pol_ix < pol_ix) {
- filter->pol_ix += 1;
- ocelot_vcap_policer_add(ocelot, filter->pol_ix,
- &filter->pol);
+ if (filter->action.police_ena &&
+ filter->action.pol_ix < pol_ix) {
+ filter->action.pol_ix += 1;
+ ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
+ &filter->action.pol);
is2_entry_set(ocelot, index, filter);
}
}
struct ocelot_vcap_filter *tmp;
struct list_head *pos, *n;
- if (filter->action == OCELOT_VCAP_ACTION_POLICE) {
+ if (filter->action.police_ena) {
block->pol_lpr--;
- filter->pol_ix = block->pol_lpr;
- ocelot_vcap_policer_add(ocelot, filter->pol_ix, &filter->pol);
+ filter->action.pol_ix = block->pol_lpr;
+ ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
+ &filter->action.pol);
}
block->count++;
list_for_each_safe(pos, q, &block->rules) {
tmp = list_entry(pos, struct ocelot_vcap_filter, list);
if (tmp->id == filter->id) {
- if (tmp->action == OCELOT_VCAP_ACTION_POLICE)
+ if (tmp->action.police_ena)
ocelot_vcap_policer_del(ocelot, block,
- tmp->pol_ix);
+ tmp->action.pol_ix);
list_del(pos);
kfree(tmp);
#include <net/sch_generic.h>
#include <net/pkt_cls.h>
+#define OCELOT_POLICER_DISCARD 0x17f
+
struct ocelot_ipv4 {
u8 addr[4];
};
enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */
};
-enum ocelot_vcap_action {
- OCELOT_VCAP_ACTION_DROP,
- OCELOT_VCAP_ACTION_TRAP,
- OCELOT_VCAP_ACTION_POLICE,
+enum ocelot_mask_mode {
+ OCELOT_MASK_MODE_NONE,
+ OCELOT_MASK_MODE_PERMIT_DENY,
+ OCELOT_MASK_MODE_POLICY,
+ OCELOT_MASK_MODE_REDIRECT,
+};
+
+struct ocelot_vcap_action {
+ union {
+ /* VCAP IS2 */
+ struct {
+ bool cpu_copy_ena;
+ u8 cpu_qu_num;
+ enum ocelot_mask_mode mask_mode;
+ unsigned long port_mask;
+ bool police_ena;
+ struct ocelot_policer pol;
+ u32 pol_ix;
+ };
+ };
};
struct ocelot_vcap_stats {
u16 prio;
u32 id;
- enum ocelot_vcap_action action;
+ struct ocelot_vcap_action action;
struct ocelot_vcap_stats stats;
unsigned long ingress_port_mask;
struct ocelot_vcap_key_ipv4 ipv4;
struct ocelot_vcap_key_ipv6 ipv6;
} key;
- struct ocelot_policer pol;
- u32 pol_ix;
};
int ocelot_vcap_filter_add(struct ocelot *ocelot,