mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
Merge branch 'mlxsw-Add-support-for-mirror-action-with-flower'
Jiri Pirko says: ==================== mlxsw: Add support for mirror action with flower Arkadi says: Add support for mirror action with flower classifier. The first 3 patches introduce a generic per-block resource infra. The last 4 patches add support for flow based span. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ebdd7b491b
@ -310,9 +310,33 @@ struct mlxsw_afa_block {
|
|||||||
struct mlxsw_afa_set *first_set;
|
struct mlxsw_afa_set *first_set;
|
||||||
struct mlxsw_afa_set *cur_set;
|
struct mlxsw_afa_set *cur_set;
|
||||||
unsigned int cur_act_index; /* In current set. */
|
unsigned int cur_act_index; /* In current set. */
|
||||||
struct list_head fwd_entry_ref_list;
|
struct list_head resource_list; /* List of resources held by actions
|
||||||
|
* in this block.
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mlxsw_afa_resource {
|
||||||
|
struct list_head list;
|
||||||
|
void (*destructor)(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_resource *resource);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mlxsw_afa_resource_add(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_resource *resource)
|
||||||
|
{
|
||||||
|
list_add(&resource->list, &block->resource_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlxsw_afa_resources_destroy(struct mlxsw_afa_block *block)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_resource *resource, *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(resource, tmp, &block->resource_list, list) {
|
||||||
|
list_del(&resource->list);
|
||||||
|
resource->destructor(block, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
|
struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
|
||||||
{
|
{
|
||||||
struct mlxsw_afa_block *block;
|
struct mlxsw_afa_block *block;
|
||||||
@ -320,7 +344,7 @@ struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
|
|||||||
block = kzalloc(sizeof(*block), GFP_KERNEL);
|
block = kzalloc(sizeof(*block), GFP_KERNEL);
|
||||||
if (!block)
|
if (!block)
|
||||||
return NULL;
|
return NULL;
|
||||||
INIT_LIST_HEAD(&block->fwd_entry_ref_list);
|
INIT_LIST_HEAD(&block->resource_list);
|
||||||
block->afa = mlxsw_afa;
|
block->afa = mlxsw_afa;
|
||||||
|
|
||||||
/* At least one action set is always present, so just create it here */
|
/* At least one action set is always present, so just create it here */
|
||||||
@ -336,8 +360,6 @@ struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlxsw_afa_block_create);
|
EXPORT_SYMBOL(mlxsw_afa_block_create);
|
||||||
|
|
||||||
static void mlxsw_afa_fwd_entry_refs_destroy(struct mlxsw_afa_block *block);
|
|
||||||
|
|
||||||
void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block)
|
void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block)
|
||||||
{
|
{
|
||||||
struct mlxsw_afa_set *set = block->first_set;
|
struct mlxsw_afa_set *set = block->first_set;
|
||||||
@ -348,7 +370,7 @@ void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block)
|
|||||||
mlxsw_afa_set_put(block->afa, set);
|
mlxsw_afa_set_put(block->afa, set);
|
||||||
set = next_set;
|
set = next_set;
|
||||||
} while (set);
|
} while (set);
|
||||||
mlxsw_afa_fwd_entry_refs_destroy(block);
|
mlxsw_afa_resources_destroy(block);
|
||||||
kfree(block);
|
kfree(block);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlxsw_afa_block_destroy);
|
EXPORT_SYMBOL(mlxsw_afa_block_destroy);
|
||||||
@ -489,10 +511,29 @@ static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct mlxsw_afa_fwd_entry_ref {
|
struct mlxsw_afa_fwd_entry_ref {
|
||||||
struct list_head list;
|
struct mlxsw_afa_resource resource;
|
||||||
struct mlxsw_afa_fwd_entry *fwd_entry;
|
struct mlxsw_afa_fwd_entry *fwd_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_afa_fwd_entry_ref_destroy(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref)
|
||||||
|
{
|
||||||
|
mlxsw_afa_fwd_entry_put(block->afa, fwd_entry_ref->fwd_entry);
|
||||||
|
kfree(fwd_entry_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_afa_fwd_entry_ref_destructor(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_resource *resource)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
|
||||||
|
|
||||||
|
fwd_entry_ref = container_of(resource, struct mlxsw_afa_fwd_entry_ref,
|
||||||
|
resource);
|
||||||
|
mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
|
||||||
|
}
|
||||||
|
|
||||||
static struct mlxsw_afa_fwd_entry_ref *
|
static struct mlxsw_afa_fwd_entry_ref *
|
||||||
mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
|
mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
|
||||||
{
|
{
|
||||||
@ -509,7 +550,8 @@ mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
|
|||||||
goto err_fwd_entry_get;
|
goto err_fwd_entry_get;
|
||||||
}
|
}
|
||||||
fwd_entry_ref->fwd_entry = fwd_entry;
|
fwd_entry_ref->fwd_entry = fwd_entry;
|
||||||
list_add(&fwd_entry_ref->list, &block->fwd_entry_ref_list);
|
fwd_entry_ref->resource.destructor = mlxsw_afa_fwd_entry_ref_destructor;
|
||||||
|
mlxsw_afa_resource_add(block, &fwd_entry_ref->resource);
|
||||||
return fwd_entry_ref;
|
return fwd_entry_ref;
|
||||||
|
|
||||||
err_fwd_entry_get:
|
err_fwd_entry_get:
|
||||||
@ -517,23 +559,51 @@ mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
|
|||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mlxsw_afa_counter {
|
||||||
|
struct mlxsw_afa_resource resource;
|
||||||
|
u32 counter_index;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mlxsw_afa_fwd_entry_ref_destroy(struct mlxsw_afa_block *block,
|
mlxsw_afa_counter_destroy(struct mlxsw_afa_block *block,
|
||||||
struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref)
|
struct mlxsw_afa_counter *counter)
|
||||||
{
|
{
|
||||||
list_del(&fwd_entry_ref->list);
|
block->afa->ops->counter_index_put(block->afa->ops_priv,
|
||||||
mlxsw_afa_fwd_entry_put(block->afa, fwd_entry_ref->fwd_entry);
|
counter->counter_index);
|
||||||
kfree(fwd_entry_ref);
|
kfree(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_afa_fwd_entry_refs_destroy(struct mlxsw_afa_block *block)
|
static void
|
||||||
|
mlxsw_afa_counter_destructor(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_resource *resource)
|
||||||
{
|
{
|
||||||
struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
|
struct mlxsw_afa_counter *counter;
|
||||||
struct mlxsw_afa_fwd_entry_ref *tmp;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(fwd_entry_ref, tmp,
|
counter = container_of(resource, struct mlxsw_afa_counter, resource);
|
||||||
&block->fwd_entry_ref_list, list)
|
mlxsw_afa_counter_destroy(block, counter);
|
||||||
mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
|
}
|
||||||
|
|
||||||
|
static struct mlxsw_afa_counter *
|
||||||
|
mlxsw_afa_counter_create(struct mlxsw_afa_block *block)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_counter *counter;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
counter = kzalloc(sizeof(*counter), GFP_KERNEL);
|
||||||
|
if (!counter)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
err = block->afa->ops->counter_index_get(block->afa->ops_priv,
|
||||||
|
&counter->counter_index);
|
||||||
|
if (err)
|
||||||
|
goto err_counter_index_get;
|
||||||
|
counter->resource.destructor = mlxsw_afa_counter_destructor;
|
||||||
|
mlxsw_afa_resource_add(block, &counter->resource);
|
||||||
|
return counter;
|
||||||
|
|
||||||
|
err_counter_index_get:
|
||||||
|
kfree(counter);
|
||||||
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MLXSW_AFA_ONE_ACTION_LEN 32
|
#define MLXSW_AFA_ONE_ACTION_LEN 32
|
||||||
@ -690,6 +760,16 @@ MLXSW_ITEM32(afa, trapdisc, forward_action, 0x00, 0, 4);
|
|||||||
*/
|
*/
|
||||||
MLXSW_ITEM32(afa, trapdisc, trap_id, 0x04, 0, 9);
|
MLXSW_ITEM32(afa, trapdisc, trap_id, 0x04, 0, 9);
|
||||||
|
|
||||||
|
/* afa_trapdisc_mirror_agent
|
||||||
|
* Mirror agent.
|
||||||
|
*/
|
||||||
|
MLXSW_ITEM32(afa, trapdisc, mirror_agent, 0x08, 29, 3);
|
||||||
|
|
||||||
|
/* afa_trapdisc_mirror_enable
|
||||||
|
* Mirror enable.
|
||||||
|
*/
|
||||||
|
MLXSW_ITEM32(afa, trapdisc, mirror_enable, 0x08, 24, 1);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
mlxsw_afa_trapdisc_pack(char *payload,
|
mlxsw_afa_trapdisc_pack(char *payload,
|
||||||
enum mlxsw_afa_trapdisc_trap_action trap_action,
|
enum mlxsw_afa_trapdisc_trap_action trap_action,
|
||||||
@ -701,6 +781,14 @@ mlxsw_afa_trapdisc_pack(char *payload,
|
|||||||
mlxsw_afa_trapdisc_trap_id_set(payload, trap_id);
|
mlxsw_afa_trapdisc_trap_id_set(payload, trap_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mlxsw_afa_trapdisc_mirror_pack(char *payload, bool mirror_enable,
|
||||||
|
u8 mirror_agent)
|
||||||
|
{
|
||||||
|
mlxsw_afa_trapdisc_mirror_enable_set(payload, mirror_enable);
|
||||||
|
mlxsw_afa_trapdisc_mirror_agent_set(payload, mirror_agent);
|
||||||
|
}
|
||||||
|
|
||||||
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
|
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
|
||||||
{
|
{
|
||||||
char *act = mlxsw_afa_block_append_action(block,
|
char *act = mlxsw_afa_block_append_action(block,
|
||||||
@ -746,6 +834,104 @@ int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);
|
EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);
|
||||||
|
|
||||||
|
struct mlxsw_afa_mirror {
|
||||||
|
struct mlxsw_afa_resource resource;
|
||||||
|
int span_id;
|
||||||
|
u8 local_in_port;
|
||||||
|
u8 local_out_port;
|
||||||
|
bool ingress;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_afa_mirror_destroy(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_mirror *mirror)
|
||||||
|
{
|
||||||
|
block->afa->ops->mirror_del(block->afa->ops_priv,
|
||||||
|
mirror->local_in_port,
|
||||||
|
mirror->local_out_port,
|
||||||
|
mirror->ingress);
|
||||||
|
kfree(mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block,
|
||||||
|
struct mlxsw_afa_resource *resource)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_mirror *mirror;
|
||||||
|
|
||||||
|
mirror = container_of(resource, struct mlxsw_afa_mirror, resource);
|
||||||
|
mlxsw_afa_mirror_destroy(block, mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mlxsw_afa_mirror *
|
||||||
|
mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
|
||||||
|
u8 local_in_port, u8 local_out_port,
|
||||||
|
bool ingress)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_mirror *mirror;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
mirror = kzalloc(sizeof(*mirror), GFP_KERNEL);
|
||||||
|
if (!mirror)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
err = block->afa->ops->mirror_add(block->afa->ops_priv,
|
||||||
|
local_in_port, local_out_port,
|
||||||
|
ingress, &mirror->span_id);
|
||||||
|
if (err)
|
||||||
|
goto err_mirror_add;
|
||||||
|
|
||||||
|
mirror->ingress = ingress;
|
||||||
|
mirror->local_out_port = local_out_port;
|
||||||
|
mirror->local_in_port = local_in_port;
|
||||||
|
mirror->resource.destructor = mlxsw_afa_mirror_destructor;
|
||||||
|
mlxsw_afa_resource_add(block, &mirror->resource);
|
||||||
|
return mirror;
|
||||||
|
|
||||||
|
err_mirror_add:
|
||||||
|
kfree(mirror);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
|
||||||
|
u8 mirror_agent)
|
||||||
|
{
|
||||||
|
char *act = mlxsw_afa_block_append_action(block,
|
||||||
|
MLXSW_AFA_TRAPDISC_CODE,
|
||||||
|
MLXSW_AFA_TRAPDISC_SIZE);
|
||||||
|
if (!act)
|
||||||
|
return -ENOBUFS;
|
||||||
|
mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP,
|
||||||
|
MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD, 0);
|
||||||
|
mlxsw_afa_trapdisc_mirror_pack(act, true, mirror_agent);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
||||||
|
u8 local_in_port, u8 local_out_port, bool ingress)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_mirror *mirror;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
mirror = mlxsw_afa_mirror_create(block, local_in_port, local_out_port,
|
||||||
|
ingress);
|
||||||
|
if (IS_ERR(mirror))
|
||||||
|
return PTR_ERR(mirror);
|
||||||
|
|
||||||
|
err = mlxsw_afa_block_append_allocated_mirror(block, mirror->span_id);
|
||||||
|
if (err)
|
||||||
|
goto err_append_allocated_mirror;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_append_allocated_mirror:
|
||||||
|
mlxsw_afa_mirror_destroy(block, mirror);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_afa_block_append_mirror);
|
||||||
|
|
||||||
/* Forwarding Action
|
/* Forwarding Action
|
||||||
* -----------------
|
* -----------------
|
||||||
* Forwarding Action can be used to implement Policy Based Switching (PBS)
|
* Forwarding Action can be used to implement Policy Based Switching (PBS)
|
||||||
@ -853,11 +1039,10 @@ mlxsw_afa_polcnt_pack(char *payload,
|
|||||||
mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
|
mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
|
||||||
u32 counter_index)
|
u32 counter_index)
|
||||||
{
|
{
|
||||||
char *act = mlxsw_afa_block_append_action(block,
|
char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_POLCNT_CODE,
|
||||||
MLXSW_AFA_POLCNT_CODE,
|
|
||||||
MLXSW_AFA_POLCNT_SIZE);
|
MLXSW_AFA_POLCNT_SIZE);
|
||||||
if (!act)
|
if (!act)
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
@ -865,6 +1050,32 @@ int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
|
|||||||
counter_index);
|
counter_index);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_afa_block_append_allocated_counter);
|
||||||
|
|
||||||
|
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
|
||||||
|
u32 *p_counter_index)
|
||||||
|
{
|
||||||
|
struct mlxsw_afa_counter *counter;
|
||||||
|
u32 counter_index;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
counter = mlxsw_afa_counter_create(block);
|
||||||
|
if (IS_ERR(counter))
|
||||||
|
return PTR_ERR(counter);
|
||||||
|
counter_index = counter->counter_index;
|
||||||
|
|
||||||
|
err = mlxsw_afa_block_append_allocated_counter(block, counter_index);
|
||||||
|
if (err)
|
||||||
|
goto err_append_allocated_counter;
|
||||||
|
|
||||||
|
if (p_counter_index)
|
||||||
|
*p_counter_index = counter_index;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_append_allocated_counter:
|
||||||
|
mlxsw_afa_counter_destroy(block, counter);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
|
EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
|
||||||
|
|
||||||
/* Virtual Router and Forwarding Domain Action
|
/* Virtual Router and Forwarding Domain Action
|
||||||
|
@ -46,6 +46,12 @@ struct mlxsw_afa_ops {
|
|||||||
void (*kvdl_set_del)(void *priv, u32 kvdl_index, bool is_first);
|
void (*kvdl_set_del)(void *priv, u32 kvdl_index, bool is_first);
|
||||||
int (*kvdl_fwd_entry_add)(void *priv, u32 *p_kvdl_index, u8 local_port);
|
int (*kvdl_fwd_entry_add)(void *priv, u32 *p_kvdl_index, u8 local_port);
|
||||||
void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index);
|
void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index);
|
||||||
|
int (*counter_index_get)(void *priv, unsigned int *p_counter_index);
|
||||||
|
void (*counter_index_put)(void *priv, unsigned int counter_index);
|
||||||
|
int (*mirror_add)(void *priv, u8 locol_in_port, u8 local_out_port,
|
||||||
|
bool ingress, int *p_span_id);
|
||||||
|
void (*mirror_del)(void *priv, u8 locol_in_port, u8 local_out_port,
|
||||||
|
bool ingress);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
|
struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
|
||||||
@ -63,12 +69,17 @@ int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
|
|||||||
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
|
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
|
||||||
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
||||||
u16 trap_id);
|
u16 trap_id);
|
||||||
|
int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
||||||
|
u8 local_in_port, u8 local_out_port,
|
||||||
|
bool ingress);
|
||||||
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
|
||||||
u8 local_port, bool in_port);
|
u8 local_port, bool in_port);
|
||||||
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
|
||||||
u16 vid, u8 pcp, u8 et);
|
u16 vid, u8 pcp, u8 et);
|
||||||
|
int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
|
||||||
|
u32 counter_index);
|
||||||
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
|
||||||
u32 counter_index);
|
u32 *p_counter_index);
|
||||||
int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid);
|
int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid);
|
||||||
int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block,
|
int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block,
|
||||||
u16 expected_irif, u16 min_mtu,
|
u16 expected_irif, u16 min_mtu,
|
||||||
|
@ -568,7 +568,7 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
|
|||||||
span_entry->used = false;
|
span_entry->used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mlxsw_sp_span_entry *
|
struct mlxsw_sp_span_entry *
|
||||||
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
|
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -669,13 +669,28 @@ mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port,
|
|||||||
static int
|
static int
|
||||||
mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
|
mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
|
||||||
struct mlxsw_sp_span_entry *span_entry,
|
struct mlxsw_sp_span_entry *span_entry,
|
||||||
enum mlxsw_sp_span_type type)
|
enum mlxsw_sp_span_type type,
|
||||||
|
bool bind)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
|
||||||
|
char mpar_pl[MLXSW_REG_MPAR_LEN];
|
||||||
|
int pa_id = span_entry->id;
|
||||||
|
|
||||||
|
/* bind the port to the SPAN entry */
|
||||||
|
mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
|
||||||
|
(enum mlxsw_reg_mpar_i_e) type, bind, pa_id);
|
||||||
|
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
|
||||||
|
struct mlxsw_sp_span_entry *span_entry,
|
||||||
|
enum mlxsw_sp_span_type type,
|
||||||
|
bool bind)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_span_inspected_port *inspected_port;
|
struct mlxsw_sp_span_inspected_port *inspected_port;
|
||||||
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
|
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
|
||||||
char mpar_pl[MLXSW_REG_MPAR_LEN];
|
|
||||||
char sbib_pl[MLXSW_REG_SBIB_LEN];
|
char sbib_pl[MLXSW_REG_SBIB_LEN];
|
||||||
int pa_id = span_entry->id;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* if it is an egress SPAN, bind a shared buffer to it */
|
/* if it is an egress SPAN, bind a shared buffer to it */
|
||||||
@ -691,12 +706,12 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bind the port to the SPAN entry */
|
if (bind) {
|
||||||
mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
|
err = mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
|
||||||
(enum mlxsw_reg_mpar_i_e) type, true, pa_id);
|
true);
|
||||||
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
|
if (err)
|
||||||
if (err)
|
goto err_port_bind;
|
||||||
goto err_mpar_reg_write;
|
}
|
||||||
|
|
||||||
inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
|
inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
|
||||||
if (!inspected_port) {
|
if (!inspected_port) {
|
||||||
@ -709,8 +724,11 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_mpar_reg_write:
|
|
||||||
err_inspected_port_alloc:
|
err_inspected_port_alloc:
|
||||||
|
if (bind)
|
||||||
|
mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
|
||||||
|
false);
|
||||||
|
err_port_bind:
|
||||||
if (type == MLXSW_SP_SPAN_EGRESS) {
|
if (type == MLXSW_SP_SPAN_EGRESS) {
|
||||||
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
|
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
|
||||||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
|
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
|
||||||
@ -719,25 +737,22 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port,
|
mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
|
||||||
struct mlxsw_sp_span_entry *span_entry,
|
struct mlxsw_sp_span_entry *span_entry,
|
||||||
enum mlxsw_sp_span_type type)
|
enum mlxsw_sp_span_type type,
|
||||||
|
bool bind)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_span_inspected_port *inspected_port;
|
struct mlxsw_sp_span_inspected_port *inspected_port;
|
||||||
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
|
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
|
||||||
char mpar_pl[MLXSW_REG_MPAR_LEN];
|
|
||||||
char sbib_pl[MLXSW_REG_SBIB_LEN];
|
char sbib_pl[MLXSW_REG_SBIB_LEN];
|
||||||
int pa_id = span_entry->id;
|
|
||||||
|
|
||||||
inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry);
|
inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry);
|
||||||
if (!inspected_port)
|
if (!inspected_port)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* remove the inspected port */
|
if (bind)
|
||||||
mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
|
mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
|
||||||
(enum mlxsw_reg_mpar_i_e) type, false, pa_id);
|
false);
|
||||||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
|
|
||||||
|
|
||||||
/* remove the SBIB buffer if it was egress SPAN */
|
/* remove the SBIB buffer if it was egress SPAN */
|
||||||
if (type == MLXSW_SP_SPAN_EGRESS) {
|
if (type == MLXSW_SP_SPAN_EGRESS) {
|
||||||
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
|
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
|
||||||
@ -750,9 +765,9 @@ mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port,
|
|||||||
kfree(inspected_port);
|
kfree(inspected_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
|
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
|
||||||
struct mlxsw_sp_port *to,
|
struct mlxsw_sp_port *to,
|
||||||
enum mlxsw_sp_span_type type)
|
enum mlxsw_sp_span_type type, bool bind)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
|
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
|
||||||
struct mlxsw_sp_span_entry *span_entry;
|
struct mlxsw_sp_span_entry *span_entry;
|
||||||
@ -765,7 +780,7 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
|
|||||||
netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
|
netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
|
||||||
span_entry->id);
|
span_entry->id);
|
||||||
|
|
||||||
err = mlxsw_sp_span_inspected_port_bind(from, span_entry, type);
|
err = mlxsw_sp_span_inspected_port_add(from, span_entry, type, bind);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_port_bind;
|
goto err_port_bind;
|
||||||
|
|
||||||
@ -776,9 +791,8 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from,
|
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
|
||||||
u8 destination_port,
|
enum mlxsw_sp_span_type type, bool bind)
|
||||||
enum mlxsw_sp_span_type type)
|
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_span_entry *span_entry;
|
struct mlxsw_sp_span_entry *span_entry;
|
||||||
|
|
||||||
@ -791,7 +805,7 @@ static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from,
|
|||||||
|
|
||||||
netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
|
netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
|
||||||
span_entry->id);
|
span_entry->id);
|
||||||
mlxsw_sp_span_inspected_port_unbind(from, span_entry, type);
|
mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
@ -1582,7 +1596,8 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
|||||||
mirror->to_local_port = to_port->local_port;
|
mirror->to_local_port = to_port->local_port;
|
||||||
mirror->ingress = ingress;
|
mirror->ingress = ingress;
|
||||||
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type);
|
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1593,8 +1608,8 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
|||||||
|
|
||||||
span_type = mirror->ingress ?
|
span_type = mirror->ingress ?
|
||||||
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
mlxsw_sp_span_mirror_remove(mlxsw_sp_port, mirror->to_local_port,
|
mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->to_local_port,
|
||||||
span_type);
|
span_type, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -396,6 +396,16 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
|
|||||||
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
|
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
|
||||||
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
|
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
|
||||||
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
|
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
|
||||||
|
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
|
||||||
|
struct mlxsw_sp_port *to,
|
||||||
|
enum mlxsw_sp_span_type type,
|
||||||
|
bool bind);
|
||||||
|
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from,
|
||||||
|
u8 destination_port,
|
||||||
|
enum mlxsw_sp_span_type type,
|
||||||
|
bool bind);
|
||||||
|
struct mlxsw_sp_span_entry *
|
||||||
|
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port);
|
||||||
|
|
||||||
/* spectrum_dcb.c */
|
/* spectrum_dcb.c */
|
||||||
#ifdef CONFIG_MLXSW_SPECTRUM_DCB
|
#ifdef CONFIG_MLXSW_SPECTRUM_DCB
|
||||||
@ -457,7 +467,6 @@ struct mlxsw_sp_acl_rule_info {
|
|||||||
struct mlxsw_afk_element_values values;
|
struct mlxsw_afk_element_values values;
|
||||||
struct mlxsw_afa_block *act_block;
|
struct mlxsw_afa_block *act_block;
|
||||||
unsigned int counter_index;
|
unsigned int counter_index;
|
||||||
bool counter_valid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mlxsw_sp_acl_profile {
|
enum mlxsw_sp_acl_profile {
|
||||||
@ -545,6 +554,10 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
|
|||||||
u16 group_id);
|
u16 group_id);
|
||||||
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
|
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
|
||||||
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
|
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
|
||||||
|
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
|
||||||
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||||||
|
struct mlxsw_sp_acl_block *block,
|
||||||
|
struct net_device *out_dev);
|
||||||
int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
|
int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
|
||||||
struct mlxsw_sp_acl_rule_info *rulei,
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||||||
struct net_device *out_dev);
|
struct net_device *out_dev);
|
||||||
|
@ -462,27 +462,6 @@ u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset)
|
|||||||
return ops->ruleset_group_id(ruleset->priv);
|
return ops->ruleset_group_id(ruleset->priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
mlxsw_sp_acl_rulei_counter_alloc(struct mlxsw_sp *mlxsw_sp,
|
|
||||||
struct mlxsw_sp_acl_rule_info *rulei)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = mlxsw_sp_flow_counter_alloc(mlxsw_sp, &rulei->counter_index);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
rulei->counter_valid = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mlxsw_sp_acl_rulei_counter_free(struct mlxsw_sp *mlxsw_sp,
|
|
||||||
struct mlxsw_sp_acl_rule_info *rulei)
|
|
||||||
{
|
|
||||||
rulei->counter_valid = false;
|
|
||||||
mlxsw_sp_flow_counter_free(mlxsw_sp, rulei->counter_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mlxsw_sp_acl_rule_info *
|
struct mlxsw_sp_acl_rule_info *
|
||||||
mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl)
|
mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl)
|
||||||
{
|
{
|
||||||
@ -587,6 +566,34 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
|
|||||||
local_port, in_port);
|
local_port, in_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
|
||||||
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||||||
|
struct mlxsw_sp_acl_block *block,
|
||||||
|
struct net_device *out_dev)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp_acl_block_binding *binding;
|
||||||
|
struct mlxsw_sp_port *out_port;
|
||||||
|
struct mlxsw_sp_port *in_port;
|
||||||
|
|
||||||
|
if (!list_is_singular(&block->binding_list))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
binding = list_first_entry(&block->binding_list,
|
||||||
|
struct mlxsw_sp_acl_block_binding, list);
|
||||||
|
in_port = binding->mlxsw_sp_port;
|
||||||
|
if (!mlxsw_sp_port_dev_check(out_dev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
out_port = netdev_priv(out_dev);
|
||||||
|
if (out_port->mlxsw_sp != mlxsw_sp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return mlxsw_afa_block_append_mirror(rulei->act_block,
|
||||||
|
in_port->local_port,
|
||||||
|
out_port->local_port,
|
||||||
|
binding->ingress);
|
||||||
|
}
|
||||||
|
|
||||||
int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
|
int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
|
||||||
struct mlxsw_sp_acl_rule_info *rulei,
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||||||
u32 action, u16 vid, u16 proto, u8 prio)
|
u32 action, u16 vid, u16 proto, u8 prio)
|
||||||
@ -619,7 +626,7 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
|
|||||||
struct mlxsw_sp_acl_rule_info *rulei)
|
struct mlxsw_sp_acl_rule_info *rulei)
|
||||||
{
|
{
|
||||||
return mlxsw_afa_block_append_counter(rulei->act_block,
|
return mlxsw_afa_block_append_counter(rulei->act_block,
|
||||||
rulei->counter_index);
|
&rulei->counter_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
|
int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
|
||||||
@ -653,13 +660,8 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
|
|||||||
goto err_rulei_create;
|
goto err_rulei_create;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mlxsw_sp_acl_rulei_counter_alloc(mlxsw_sp, rule->rulei);
|
|
||||||
if (err)
|
|
||||||
goto err_counter_alloc;
|
|
||||||
return rule;
|
return rule;
|
||||||
|
|
||||||
err_counter_alloc:
|
|
||||||
mlxsw_sp_acl_rulei_destroy(rule->rulei);
|
|
||||||
err_rulei_create:
|
err_rulei_create:
|
||||||
kfree(rule);
|
kfree(rule);
|
||||||
err_alloc:
|
err_alloc:
|
||||||
@ -672,7 +674,6 @@ void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp,
|
|||||||
{
|
{
|
||||||
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
|
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
|
||||||
|
|
||||||
mlxsw_sp_acl_rulei_counter_free(mlxsw_sp, rule->rulei);
|
|
||||||
mlxsw_sp_acl_rulei_destroy(rule->rulei);
|
mlxsw_sp_acl_rulei_destroy(rule->rulei);
|
||||||
kfree(rule);
|
kfree(rule);
|
||||||
mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset);
|
mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset);
|
||||||
|
@ -108,11 +108,77 @@ static void mlxsw_sp_act_kvdl_fwd_entry_del(void *priv, u32 kvdl_index)
|
|||||||
mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
|
mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_act_counter_index_get(void *priv, unsigned int *p_counter_index)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp *mlxsw_sp = priv;
|
||||||
|
|
||||||
|
return mlxsw_sp_flow_counter_alloc(mlxsw_sp, p_counter_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp *mlxsw_sp = priv;
|
||||||
|
|
||||||
|
mlxsw_sp_flow_counter_free(mlxsw_sp, counter_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port,
|
||||||
|
bool ingress, int *p_span_id)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp_port *in_port, *out_port;
|
||||||
|
struct mlxsw_sp_span_entry *span_entry;
|
||||||
|
struct mlxsw_sp *mlxsw_sp = priv;
|
||||||
|
enum mlxsw_sp_span_type type;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
|
out_port = mlxsw_sp->ports[local_out_port];
|
||||||
|
in_port = mlxsw_sp->ports[local_in_port];
|
||||||
|
|
||||||
|
err = mlxsw_sp_span_mirror_add(in_port, out_port, type, false);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
span_entry = mlxsw_sp_span_entry_find(mlxsw_sp, local_out_port);
|
||||||
|
if (!span_entry) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto err_span_entry_find;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p_span_id = span_entry->id;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_span_entry_find:
|
||||||
|
mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, u8 local_out_port,
|
||||||
|
bool ingress)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp *mlxsw_sp = priv;
|
||||||
|
struct mlxsw_sp_port *in_port;
|
||||||
|
enum mlxsw_sp_span_type type;
|
||||||
|
|
||||||
|
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
|
in_port = mlxsw_sp->ports[local_in_port];
|
||||||
|
|
||||||
|
mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = {
|
static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = {
|
||||||
.kvdl_set_add = mlxsw_sp_act_kvdl_set_add,
|
.kvdl_set_add = mlxsw_sp_act_kvdl_set_add,
|
||||||
.kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
|
.kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
|
||||||
.kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
|
.kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
|
||||||
.kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
|
.kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
|
||||||
|
.counter_index_get = mlxsw_sp_act_counter_index_get,
|
||||||
|
.counter_index_put = mlxsw_sp_act_counter_index_put,
|
||||||
|
.mirror_add = mlxsw_sp_act_mirror_add,
|
||||||
|
.mirror_del = mlxsw_sp_act_mirror_del,
|
||||||
};
|
};
|
||||||
|
|
||||||
int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp)
|
int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
|
@ -108,6 +108,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
|||||||
out_dev);
|
out_dev);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
} else if (is_tcf_mirred_egress_mirror(a)) {
|
||||||
|
struct net_device *out_dev = tcf_mirred_dev(a);
|
||||||
|
|
||||||
|
err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei,
|
||||||
|
block, out_dev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
} else if (is_tcf_vlan(a)) {
|
} else if (is_tcf_vlan(a)) {
|
||||||
u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
|
u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
|
||||||
u32 action = tcf_vlan_action(a);
|
u32 action = tcf_vlan_action(a);
|
||||||
|
@ -243,7 +243,8 @@ mlxsw_sp_mr_tcam_afa_block_create(struct mlxsw_sp *mlxsw_sp,
|
|||||||
if (!afa_block)
|
if (!afa_block)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
err = mlxsw_afa_block_append_counter(afa_block, counter_index);
|
err = mlxsw_afa_block_append_allocated_counter(afa_block,
|
||||||
|
counter_index);
|
||||||
if (err)
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user