osi: l3l4: split perfect inv bit for each field

- HW has separate Inverse Match bits in l3l4 control register for each
  source address, destination address, source port and destination port.
- Hence, added separate Inverse match bits for all the 4 fields in
  osi l3l4 structure to provide flexibility for l3l4 users.
- Fixed validation parameter sequence to validate l3l4 parameters
  before processing filter data.

Bug 3576506
Bug 3825731

Change-Id: Id7f8939acd92ad5799f2ad0d7cef5d4fcb7e00c5
Signed-off-by: Hareesh Kesireddy <hkesireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/2820517
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Hareesh Kesireddy
2022-12-02 13:19:02 +05:30
committed by Bhadram Varka
parent 424f7987df
commit e2cf4313dc
4 changed files with 117 additions and 87 deletions

View File

@@ -42,8 +42,6 @@ struct osi_l3_l4_filter {
nveu32_t is_udp;
/** ipv6 (OSI_TRUE) or ipv4 (OSI_FALSE) */
nveu32_t is_ipv6;
/** perfect(OSI_FALSE) or inverse(OSI_TRUE) */
nveu32_t perfect_inverse_match;
#endif /* !OSI_STRIPPED_LIB */
/** destination ip address information */
struct {
@@ -56,8 +54,12 @@ struct osi_l3_l4_filter {
nveu16_t port_no;
/** addr match enable (OSI_TRUE) or disable (OSI_FALSE) */
nveu32_t addr_match;
/** perfect(OSI_FALSE) or inverse(OSI_TRUE) match for address */
nveu32_t addr_match_inv;
/** port match enable (OSI_TRUE) or disable (OSI_FALSE) */
nveu32_t port_match;
/** perfect(OSI_FALSE) or inverse(OSI_TRUE) match for port */
nveu32_t port_match_inv;
#endif /* !OSI_STRIPPED_LIB */
} dst;
#ifndef OSI_STRIPPED_LIB
@@ -71,8 +73,12 @@ struct osi_l3_l4_filter {
nveu16_t port_no;
/** addr match enable (OSI_TRUE) or disable (OSI_FALSE) */
nveu32_t addr_match;
/** perfect(OSI_FALSE) or inverse(OSI_TRUE) match for address */
nveu32_t addr_match_inv;
/** port match enable (OSI_TRUE) or disable (OSI_FALSE) */
nveu32_t port_match;
/** perfect(OSI_FALSE) or inverse(OSI_TRUE) match for port */
nveu32_t port_match_inv;
} src;
#endif /* !OSI_STRIPPED_LIB */
} data;

View File

@@ -1516,19 +1516,12 @@ static void prepare_l3l4_ctr_reg(const struct osi_core_priv_data *const osi_core
nveu32_t *ctr_reg)
{
#ifndef OSI_STRIPPED_LIB
nveu32_t perfect_inverse_match = l3_l4->data.perfect_inverse_match;
nveu32_t dma_routing_enable = l3_l4->dma_routing_enable;
nveu32_t dst_addr_match = l3_l4->data.dst.addr_match;
#else
nveu32_t perfect_inverse_match = OSI_FALSE;
nveu32_t dma_routing_enable = OSI_TRUE;
nveu32_t dst_addr_match = OSI_TRUE;
#endif /* !OSI_STRIPPED_LIB */
const nveu32_t dma_chan_shift[2] = {
EQOS_MAC_L3L4_CTR_DMCHN_SHIFT,
MGBE_MAC_L3L4_CTR_DMCHN_SHIFT
};
const nveu32_t dma_chan_en_shift[2] = {
EQOS_MAC_L3L4_CTR_DMCHEN_SHIFT,
MGBE_MAC_L3L4_CTR_DMCHEN_SHIFT
@@ -1537,24 +1530,26 @@ static void prepare_l3l4_ctr_reg(const struct osi_core_priv_data *const osi_core
/* set routing dma channel */
value |= dma_routing_enable << (dma_chan_en_shift[osi_core->mac] & 0x1FU);
value |= l3_l4->dma_chan << (dma_chan_shift[osi_core->mac] & 0x1FU);
value |= l3_l4->dma_chan << MAC_L3L4_CTR_DMCHN_SHIFT;
/* Enable L3 filters for IPv4 DESTINATION addr matching */
value |= (dst_addr_match << MAC_L3L4_CTR_L3DAM_SHIFT) |
(perfect_inverse_match << MAC_L3L4_CTR_L3DAIM_SHIFT);
value |= dst_addr_match << MAC_L3L4_CTR_L3DAM_SHIFT;
#ifndef OSI_STRIPPED_LIB
/* Enable L3 filters for IPv4 DESTINATION addr INV matching */
value |= l3_l4->data.dst.addr_match_inv << MAC_L3L4_CTR_L3DAIM_SHIFT;
/* Enable L3 filters for IPv4 SOURCE addr matching */
value |= (l3_l4->data.src.addr_match << MAC_L3L4_CTR_L3SAM_SHIFT) |
(perfect_inverse_match << MAC_L3L4_CTR_L3SAIM_SHIFT);
(l3_l4->data.src.addr_match_inv << MAC_L3L4_CTR_L3SAIM_SHIFT);
/* Enable L4 filters for DESTINATION port No matching */
value |= (l3_l4->data.dst.port_match << MAC_L3L4_CTR_L4DPM_SHIFT) |
(perfect_inverse_match << MAC_L3L4_CTR_L4DPIM_SHIFT);
(l3_l4->data.dst.port_match_inv << MAC_L3L4_CTR_L4DPIM_SHIFT);
/* Enable L4 filters for SOURCE Port No matching */
value |= (l3_l4->data.src.port_match << MAC_L3L4_CTR_L4SPM_SHIFT) |
(perfect_inverse_match << MAC_L3L4_CTR_L4SPIM_SHIFT);
(l3_l4->data.src.port_match_inv << MAC_L3L4_CTR_L4SPIM_SHIFT);
/* set udp / tcp port matching bit (for l4) */
value |= l3_l4->data.is_udp << MAC_L3L4_CTR_L4PEN_SHIFT;

View File

@@ -105,17 +105,16 @@
#define MAC_L3L4_CTR_L3SAIM_SHIFT 3
#endif /* !OSI_STRIPPED_LIB */
#define MAC_L3L4_CTR_L3DAM_SHIFT 4
#define MAC_L3L4_CTR_L3DAIM_SHIFT 5
#ifndef OSI_STRIPPED_LIB
#define MAC_L3L4_CTR_L3DAIM_SHIFT 5
#define MAC_L3L4_CTR_L4PEN_SHIFT 16
#define MAC_L3L4_CTR_L4SPM_SHIFT 18
#define MAC_L3L4_CTR_L4SPIM_SHIFT 19
#define MAC_L3L4_CTR_L4DPM_SHIFT 20
#define MAC_L3L4_CTR_L4DPIM_SHIFT 21
#endif /* !OSI_STRIPPED_LIB */
#define EQOS_MAC_L3L4_CTR_DMCHN_SHIFT 24 /* 3 bits */
#define MAC_L3L4_CTR_DMCHN_SHIFT 24
#define EQOS_MAC_L3L4_CTR_DMCHEN_SHIFT 28
#define MGBE_MAC_L3L4_CTR_DMCHN_SHIFT 24 /* 4 bits */
#define MGBE_MAC_L3L4_CTR_DMCHEN_SHIFT 31
/**

View File

@@ -793,12 +793,94 @@ static nve32_t l3l4_find_match(const struct core_local *const l_core,
}
/**
* @brief configure_l3l4_filter_helper - helper function for l3l4 configuration
* @brief configure_l3l4_filter_valid_params - parameter validation function for l3l4 configuration
*
* @note
* Algorithm:
* - Validate all the l3_l4 structure parameter.
* Return -1 if parameter validation fails.
* - Verify routing dma channel id value.
* - Vefify each enable/disable parameters is <= OSI_TRUE.
* - Return -1 if parameter validation fails.
* - Return 0 on success.
*
* @param[inout] l_core: OSI local core data structure.
* @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter)
*
* @pre
* - MAC should be initialized and started. see osi_start_mac()
*
* @retval 0 on success
* @retval -1 on failure.
*/
static nve32_t configure_l3l4_filter_valid_params(const struct osi_core_priv_data *const osi_core,
const struct osi_l3_l4_filter *const l3_l4)
{
const nveu32_t max_dma_chan[2] = {
OSI_EQOS_MAX_NUM_CHANS,
OSI_MGBE_MAX_NUM_CHANS
};
nve32_t ret = -1;
/* validate dma channel */
if (l3_l4->dma_chan > max_dma_chan[osi_core->mac]) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: Wrong DMA channel: "), (l3_l4->dma_chan));
goto exit_func;
}
/* valate enb parameters */
if ((l3_l4->filter_enb_dis
#ifndef OSI_STRIPPED_LIB
| l3_l4->dma_routing_enable |
l3_l4->data.is_udp |
l3_l4->data.is_ipv6 |
l3_l4->data.src.port_match |
l3_l4->data.src.addr_match |
l3_l4->data.dst.port_match |
l3_l4->data.dst.addr_match |
l3_l4->data.src.port_match_inv |
l3_l4->data.src.addr_match_inv |
l3_l4->data.dst.port_match_inv |
l3_l4->data.dst.addr_match_inv
#endif /* !OSI_STRIPPED_LIB */
) > OSI_TRUE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: one of the enb param > OSI_TRUE: "), 0);
goto exit_func;
}
#ifndef OSI_STRIPPED_LIB
/* validate port/addr enb bits */
if (l3_l4->filter_enb_dis == OSI_TRUE) {
if ((l3_l4->data.src.port_match | l3_l4->data.src.addr_match |
l3_l4->data.dst.port_match | l3_l4->data.dst.addr_match)
== OSI_FALSE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: None of the enb bits are not set: "), 0);
goto exit_func;
}
if ((l3_l4->data.is_ipv6 & l3_l4->data.src.addr_match &
l3_l4->data.dst.addr_match) != OSI_FALSE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: Both ip6 addr match bits are set\n"), 0);
goto exit_func;
}
}
#endif /* !OSI_STRIPPED_LIB */
/* success */
ret = 0;
exit_func:
return ret;
}
/**
* @brief configure_l3l4_filter_helper - helper function for l3l4 configuration
*
* @note
* Algorithm:
* - Confifure l3l4 filter using l_core->ops_p->config_l3l4_filters().
* Return -1 if config_l3l4_filters() fails.
* - Store the filter into l_core->cfg.l3_l4[] and enable
@@ -820,69 +902,7 @@ static nve32_t configure_l3l4_filter_helper(struct osi_core_priv_data *const osi
{
struct osi_l3_l4_filter *cfg_l3_l4;
struct core_local *const l_core = (struct core_local *)(void *)osi_core;
const nveu32_t max_filter_no[2] = {
EQOS_MAX_L3_L4_FILTER,
OSI_MGBE_MAX_L3_L4_FILTER
};
const nveu32_t max_dma_chan[2] = {
OSI_EQOS_MAX_NUM_CHANS,
OSI_MGBE_MAX_NUM_CHANS
};
nve32_t ret = -1;
/* validate filter index */
if (filter_no >= max_filter_no[osi_core->mac]) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("invalid filter index for L3/L4 filter\n"), (filter_no));
goto exit_func;
}
/* validate dma channel */
if (l3_l4->dma_chan > max_dma_chan[osi_core->mac]) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: Wrong DMA channel: "), (l3_l4->dma_chan));
goto exit_func;
}
/* valate enb parameters */
if ((
#ifndef OSI_STRIPPED_LIB
l3_l4->dma_routing_enable |
l3_l4->data.is_udp |
l3_l4->data.is_ipv6 |
l3_l4->data.perfect_inverse_match |
l3_l4->data.src.port_match |
l3_l4->data.src.addr_match |
l3_l4->data.dst.port_match |
l3_l4->data.dst.addr_match |
#endif /* !OSI_STRIPPED_LIB */
l3_l4->filter_enb_dis
) > OSI_TRUE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: one of the enb param > OSI_TRUE: "), (filter_no));
goto exit_func;
}
#ifndef OSI_STRIPPED_LIB
/* validate port/addr enb bits */
if (l3_l4->filter_enb_dis == OSI_TRUE) {
if ((l3_l4->data.src.port_match | l3_l4->data.src.addr_match |
l3_l4->data.dst.port_match | l3_l4->data.dst.addr_match)
== OSI_FALSE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: None of the enb bits are not set: "),
(filter_no));
goto exit_func;
}
if ((l3_l4->data.is_ipv6 & l3_l4->data.src.addr_match &
l3_l4->data.dst.addr_match) != OSI_FALSE) {
OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND),
("L3L4: Both ip6 addr match bits are set\n"),
(filter_no));
goto exit_func;
}
}
#endif /* !OSI_STRIPPED_LIB */
nve32_t ret;
ret = l_core->ops_p->config_l3l4_filters(osi_core, filter_no, l3_l4);
if (ret < 0) {
@@ -902,7 +922,7 @@ static nve32_t configure_l3l4_filter_helper(struct osi_core_priv_data *const osi
("L3L4: ADD: "), (filter_no));
/* update filter mask bit */
osi_core->l3l4_filter_bitmask |= (((nveu32_t)1U << filter_no) & 0x1FU);
osi_core->l3l4_filter_bitmask |= ((nveu32_t)1U << (filter_no & 0x1FU));
} else {
/* Clear the filter data.
* osi_memset is an internal function and it cannot fail, hence
@@ -913,7 +933,7 @@ static nve32_t configure_l3l4_filter_helper(struct osi_core_priv_data *const osi
("L3L4: DELETE: "), (filter_no));
/* update filter mask bit */
osi_core->l3l4_filter_bitmask &= ~(((nveu32_t)1U << filter_no) & 0x1FU);
osi_core->l3l4_filter_bitmask &= ~((nveu32_t)1U << (filter_no & 0x1FU));
}
if (osi_core->l3l4_filter_bitmask != 0U) {
@@ -960,11 +980,14 @@ static void l3l4_add_wildcard_filter(struct osi_core_priv_data *const osi_core,
osi_memset(l3l4_filter, 0, sizeof(struct osi_l3_l4_filter));
l3l4_filter->filter_enb_dis = OSI_TRUE;
l3l4_filter->data.is_udp = OSI_TRUE;
l3l4_filter->data.perfect_inverse_match = OSI_TRUE;
l3l4_filter->data.src.port_match = OSI_TRUE;
l3l4_filter->data.dst.port_match = OSI_TRUE;
l3l4_filter->data.src.port_match_inv = OSI_TRUE;
l3l4_filter->data.src.addr_match = OSI_TRUE;
l3l4_filter->data.src.addr_match_inv = OSI_TRUE;
l3l4_filter->data.dst.port_match = OSI_TRUE;
l3l4_filter->data.dst.port_match_inv = OSI_TRUE;
l3l4_filter->data.dst.addr_match = OSI_TRUE;
l3l4_filter->data.dst.addr_match_inv = OSI_TRUE;
/* configure wildcard at last filter index */
err = configure_l3l4_filter_helper(osi_core, max_filter_no, l3l4_filter);
@@ -988,6 +1011,8 @@ static void l3l4_add_wildcard_filter(struct osi_core_priv_data *const osi_core,
*
* @note
* Algorithm:
* - Validate all the l3_l4 structure parameter using configure_l3l4_filter_valid_params().
* Return -1 if parameter validation fails.
* - For filter enable case,
* -> If filter already enabled, return -1 to report error.
* -> Otherwise find free index and configure filter using configure_l3l4_filter_helper().
@@ -1022,6 +1047,11 @@ static nve32_t configure_l3l4_filter(struct osi_core_priv_data *const osi_core,
};
nve32_t ret = -1;
if (configure_l3l4_filter_valid_params(osi_core, l3_l4) < 0) {
/* parameter validation failed */
goto exit_func;
}
/* search for a duplicate filter request or find for free index */
err = l3l4_find_match(l_core, l3_l4, &filter_no, &free_filter_no,
max_filter_no[osi_core->mac]);