diff --git a/include/nvethernetrm_l3l4.h b/include/nvethernetrm_l3l4.h index 65e8c7b..dd8619a 100644 --- a/include/nvethernetrm_l3l4.h +++ b/include/nvethernetrm_l3l4.h @@ -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; diff --git a/osi/core/core_common.c b/osi/core/core_common.c index c977db5..309efbd 100644 --- a/osi/core/core_common.c +++ b/osi/core/core_common.c @@ -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; diff --git a/osi/core/core_common.h b/osi/core/core_common.h index 58fe13a..5634966 100644 --- a/osi/core/core_common.h +++ b/osi/core/core_common.h @@ -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 /** diff --git a/osi/core/osi_hal.c b/osi/core/osi_hal.c index 61175fd..2161e64 100644 --- a/osi/core/osi_hal.c +++ b/osi/core/osi_hal.c @@ -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]);