blob: 5ca8a6fedcb055dca7029dcab505f7504556f0c6 [file] [log] [blame]
/*
* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* @defgroup dess_igmp DESS_IGMP
* @{
*/
#include "sw.h"
#include "hsl.h"
#include "hsl_dev.h"
#include "hsl_port_prop.h"
#include "dess_igmp.h"
#include "dess_reg.h"
#define LEAVE_EN_OFFSET 2
#define JOIN_EN_OFFSET 1
#define IGMP_MLD_EN_OFFSET 0
#define DESS_MAX_PORT_LEARN_LIMIT_CNT 1024
extern sw_error_t
dess_igmp_sg_entry_set(a_uint32_t dev_id, fal_igmp_sg_entry_t * entry);
extern sw_error_t
dess_igmp_sg_entry_clear(a_uint32_t dev_id, fal_igmp_sg_entry_t * entry);
extern sw_error_t
dess_igmp_sg_entry_show(a_uint32_t dev_id);
extern sw_error_t
dess_igmp_sg_entry_query(a_uint32_t dev_id, fal_igmp_sg_info_t * info);
static sw_error_t
_dess_port_igmp_property_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable, a_uint32_t item)
{
sw_error_t rv;
a_uint32_t reg = 0, val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
if (A_TRUE == enable)
{
val = 1;
}
else if (A_FALSE == enable)
{
val = 0;
}
else
{
return SW_BAD_PARAM;
}
if (3 >= port_id)
{
HSL_REG_ENTRY_GET(rv, dev_id, FRAME_ACK_CTL0, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
reg &= ~(0x1UL << ((port_id << 3) + item));
reg |= (val << ((port_id << 3) + item));
HSL_REG_ENTRY_SET(rv, dev_id, FRAME_ACK_CTL0, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
}
else
{
HSL_REG_ENTRY_GET(rv, dev_id, FRAME_ACK_CTL1, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
reg &= ~(0x1UL << (((port_id - 4) << 3) + item));
reg |= (val << (((port_id - 4) << 3) + item));
HSL_REG_ENTRY_SET(rv, dev_id, FRAME_ACK_CTL1, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
}
return rv;
}
static sw_error_t
_dess_port_igmp_property_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable, a_uint32_t item)
{
sw_error_t rv;
a_uint32_t reg = 0, val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
if (3 >= port_id)
{
HSL_REG_ENTRY_GET(rv, dev_id, FRAME_ACK_CTL0, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
val = (reg >> ((port_id << 3) + item)) & 0x1UL;
}
else
{
HSL_REG_ENTRY_GET(rv, dev_id, FRAME_ACK_CTL1, 0,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
val = (reg >> (((port_id - 4) << 3) + item)) & 0x1UL;
}
if (1 == val)
{
*enable = A_TRUE;
}
else
{
*enable = A_FALSE;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_cmd_set(a_uint32_t dev_id, fal_fwd_cmd_t cmd)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (FAL_MAC_CPY_TO_CPU == cmd)
{
val = 1;
}
else if (FAL_MAC_RDT_TO_CPU == cmd)
{
val = 0;
}
else
{
return SW_NOT_SUPPORTED;
}
HSL_REG_FIELD_SET(rv, dev_id, FORWARD_CTL0, 0, IGMP_COPY_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_cmd_get(a_uint32_t dev_id, fal_fwd_cmd_t * cmd)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, FORWARD_CTL0, 0, IGMP_COPY_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (1 == val)
{
*cmd = FAL_MAC_CPY_TO_CPU;
}
else
{
*cmd = FAL_MAC_RDT_TO_CPU;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_rp_set(a_uint32_t dev_id, fal_pbmp_t pts)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (A_FALSE == hsl_mports_validity_check(dev_id, pts))
{
return SW_BAD_PARAM;
}
val = pts;
HSL_REG_FIELD_SET(rv, dev_id, FORWARD_CTL1, 0, IGMP_DP,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_rp_get(a_uint32_t dev_id, fal_pbmp_t * pts)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, FORWARD_CTL1, 0, IGMP_DP,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
*pts = val;
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_entry_creat_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE == enable)
{
val = 1;
}
else if (A_FALSE == enable)
{
val = 0;
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_CREAT_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_entry_creat_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_CREAT_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (val)
{
*enable = A_TRUE;
}
else
{
*enable = A_FALSE;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_entry_static_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE == enable)
{
val = 0xf;
}
else if (A_FALSE == enable)
{
val = 0xe;
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_JOIN_STATIC,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_entry_static_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_JOIN_STATIC,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (0xf == val)
{
*enable = A_TRUE;
}
else
{
*enable = A_FALSE;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_entry_leaky_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE == enable)
{
val = 1;
}
else if (A_FALSE == enable)
{
val = 0;
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_JOIN_LEAKY,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_entry_leaky_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, IGMP_JOIN_LEAKY,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (val)
{
*enable = A_TRUE;
}
else
{
*enable = A_FALSE;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_entry_v3_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
a_uint32_t val;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE == enable)
{
val = 1;
}
else if (A_FALSE == enable)
{
val = 0;
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_FIELD_SET(rv, dev_id, FRAME_ACK_CTL1, 0, IGMP_V3_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_entry_v3_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
a_uint32_t val = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_FIELD_GET(rv, dev_id, FRAME_ACK_CTL1, 0, IGMP_V3_EN,
(a_uint8_t *) (&val), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (val)
{
*enable = A_TRUE;
}
else
{
*enable = A_FALSE;
}
return SW_OK;
}
static sw_error_t
_dess_igmp_mld_entry_queue_set(a_uint32_t dev_id, a_bool_t enable,
a_uint32_t queue)
{
sw_error_t rv;
a_uint32_t entry = 0;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_CTL, 0,
(a_uint8_t *) (&entry), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (A_TRUE == enable)
{
SW_SET_REG_BY_FIELD(ADDR_TABLE_CTL, IGMP_PRI_EN, 1, entry);
SW_SET_REG_BY_FIELD(ADDR_TABLE_CTL, IGMP_PRI, queue, entry);
}
else if (A_FALSE == enable)
{
SW_SET_REG_BY_FIELD(ADDR_TABLE_CTL, IGMP_PRI_EN, 0, entry);
SW_SET_REG_BY_FIELD(ADDR_TABLE_CTL, IGMP_PRI, 0, entry);
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_CTL, 0,
(a_uint8_t *) (&entry), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_igmp_mld_entry_queue_get(a_uint32_t dev_id, a_bool_t * enable,
a_uint32_t * queue)
{
sw_error_t rv;
a_uint32_t entry = 0, data;
HSL_DEV_ID_CHECK(dev_id);
HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_CTL, 0,
(a_uint8_t *) (&entry), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
SW_GET_FIELD_BY_REG(ADDR_TABLE_CTL, IGMP_PRI_EN, data, entry);
if (data)
{
*enable = A_TRUE;
SW_GET_FIELD_BY_REG(ADDR_TABLE_CTL, IGMP_PRI, data, entry);
*queue = data;
}
else
{
*enable = A_FALSE;
*queue = 0;
}
return SW_OK;
}
static sw_error_t
_dess_port_igmp_mld_learn_limit_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable, a_uint32_t cnt)
{
sw_error_t rv;
a_uint32_t reg = 0;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
HSL_REG_ENTRY_GET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (A_TRUE == enable)
{
if (DESS_MAX_PORT_LEARN_LIMIT_CNT < cnt)
{
return SW_BAD_PARAM;
}
SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_LIMIT_EN, 1, reg);
SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_CNT, cnt, reg);
}
else if (A_FALSE == enable)
{
SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_LIMIT_EN, 0, reg);
SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_CNT, 0, reg);
}
else
{
return SW_BAD_PARAM;
}
HSL_REG_ENTRY_SET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_port_igmp_mld_learn_limit_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable, a_uint32_t * cnt)
{
sw_error_t rv;
a_uint32_t data, reg = 0;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
HSL_REG_ENTRY_GET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id,
(a_uint8_t *) (&reg), sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
SW_GET_FIELD_BY_REG(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_LIMIT_EN, data, reg);
if (data)
{
SW_GET_FIELD_BY_REG(PORT_LEARN_LIMIT_CTL, IGMP_JOIN_CNT, data, reg);
*enable = A_TRUE;
*cnt = data;
}
else
{
*enable = A_FALSE;
*cnt = data;
}
return SW_OK;
}
static sw_error_t
_dess_port_igmp_mld_learn_exceed_cmd_set(a_uint32_t dev_id, fal_port_t port_id,
fal_fwd_cmd_t cmd)
{
sw_error_t rv;
a_uint32_t data = 0;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
if (FAL_MAC_DROP == cmd)
{
data = 1;
}
else if (FAL_MAC_RDT_TO_CPU == cmd)
{
data = 0;
}
else
{
return SW_NOT_SUPPORTED;
}
HSL_REG_FIELD_SET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id,
IGMP_JOIN_LIMIT_DROP_EN, (a_uint8_t *) (&data),
sizeof (a_uint32_t));
return rv;
}
static sw_error_t
_dess_port_igmp_mld_learn_exceed_cmd_get(a_uint32_t dev_id, fal_port_t port_id,
fal_fwd_cmd_t * cmd)
{
sw_error_t rv;
a_uint32_t data = 0;
HSL_DEV_ID_CHECK(dev_id);
if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
{
return SW_BAD_PARAM;
}
HSL_REG_FIELD_GET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id,
IGMP_JOIN_LIMIT_DROP_EN, (a_uint8_t *) (&data),
sizeof (a_uint32_t));
SW_RTN_ON_ERROR(rv);
if (data)
{
*cmd = FAL_MAC_DROP;
}
else
{
*cmd = FAL_MAC_RDT_TO_CPU;
}
return SW_OK;
}
/**
* @brief Set igmp/mld packets snooping status on a particular port.
* @details Comments:
* After enabling igmp/mld snooping feature on a particular port all kinds
* igmp/mld packets received on this port would be acknowledged by hardware.
* Particular forwarding decision could be setted by fal_igmp_mld_cmd_set.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmps_status_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_set(dev_id, port_id, enable,
IGMP_MLD_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmp/mld packets snooping status on particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmps_status_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_get(dev_id, port_id, enable,
IGMP_MLD_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set igmp/mld packets forwarding command on a particular device.
* @details Comments:
* Particular device may only support parts of forwarding commands.
* This operation will take effect only after enabling igmp/mld snooping
* @param[in] dev_id device id
* @param[in] cmd forwarding command
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_cmd_set(a_uint32_t dev_id, fal_fwd_cmd_t cmd)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_cmd_set(dev_id, cmd);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmp/mld packets forwarding command on a particular device.
* @param[in] dev_id device id
* @param[out] cmd forwarding command
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_cmd_get(a_uint32_t dev_id, fal_fwd_cmd_t * cmd)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_cmd_get(dev_id, cmd);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set igmp/mld join packets hardware acknowledgement status on particular port.
* @details Comments:
* After enabling igmp/mld join feature on a particular port hardware will
* dynamic learning or changing multicast entry.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_join_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_set(dev_id, port_id, enable, JOIN_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmp/mld join packets hardware acknowledgement status on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_join_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_get(dev_id, port_id, enable, JOIN_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set igmp/mld leave packets hardware acknowledgement status on a particular port.
* @details Comments:
* After enabling igmp leave feature on a particular port hardware will dynamic
* deleting or changing multicast entry.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_leave_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_set(dev_id, port_id, enable, LEAVE_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmp/mld leave packets hardware acknowledgement status on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_leave_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_property_get(dev_id, port_id, enable, LEAVE_EN_OFFSET);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set igmp/mld router ports on a particular device.
* @details Comments:
* After enabling igmp/mld join/leave feature on a particular port igmp/mld
* join/leave packets received on this port will be forwarded to router ports.
* @param[in] dev_id device id
* @param[in] pts dedicates ports
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_rp_set(a_uint32_t dev_id, fal_pbmp_t pts)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_rp_set(dev_id, pts);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmp/mld router ports on a particular device.
* @param[in] dev_id device id
* @param[out] pts dedicates ports
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_rp_get(a_uint32_t dev_id, fal_pbmp_t * pts)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_rp_get(dev_id, pts);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set the status of creating multicast entry during igmp/mld join/leave procedure.
* @details Comments:
* After enabling igmp/mld join/leave feature on a particular port if enable
* entry creat hardware will dynamic creat and delete multicast entry,
* otherwise hardware only can change destination ports of existing muticast entry.
* @param[in] dev_id device id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_creat_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_creat_set(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get the status of creating multicast entry during igmp/mld join/leave procedure.
* @param[in] dev_id device id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_creat_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_creat_get(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set the static status of multicast entry which learned by hardware.
* @details Comments:
* After enabling igmp/mld join/leave feature on a particular port if enable
* static status hardware will not age out multicast entry which leardned by hardware,
* otherwise hardware will age out multicast entry which leardned by hardware.
* @param[in] dev_id device id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_static_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_static_set(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get the static status of multicast entry which learned by hardware.
* @param[in] dev_id device id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_static_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_static_get(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set the leaky status of multicast entry which learned by hardware.
* @details Comments:
* After enabling igmp/mld join/leave feature on a particular port if enable
* leaky status hardware will set leaky flag of multicast entry which leardned by hardware,
* otherwise hardware will not set leaky flag of multicast entry which leardned by hardware.
* @param[in] dev_id device id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_leaky_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_leaky_set(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get the leaky status of multicast entry which learned by hardware.
* @param[in] dev_id device id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_leaky_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_leaky_get(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set igmpv3/mldv2 packets hardware acknowledgement status on a particular device.
* @details Comments:
* After enabling igmp join/leave feature on a particular port hardware will dynamic
* creating or changing multicast entry after receiving igmpv3/mldv2 packets.
* @param[in] dev_id device id
* @param[in] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_v3_set(a_uint32_t dev_id, a_bool_t enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_v3_set(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get igmpv3/mldv2 packets hardware acknowledgement status on a particular device.
* @param[in] dev_id device id
* @param[out] enable A_TRUE or A_FALSE
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_v3_get(a_uint32_t dev_id, a_bool_t * enable)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_v3_get(dev_id, enable);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set the queue status of multicast entry which learned by hardware.
* @details Comments:
* After enabling igmp/mld join/leave feature on a particular port if enable
* leaky status hardware will set queue flag of multicast entry which leardned by hardware,
* otherwise hardware will not set queue flag of multicast entry which leardned by hardware.
* @param[in] dev_id device id
* @param[in] enable A_TRUE or A_FALSE
* @param[in] queue queue id
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_queue_set(a_uint32_t dev_id, a_bool_t enable,
a_uint32_t queue)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_queue_set(dev_id, enable, queue);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get the queue status of multicast entry which learned by hardware.
* @param[in] dev_id device id
* @param[out] enable A_TRUE or A_FALSE
* @param[out] queue queue id
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_igmp_mld_entry_queue_get(a_uint32_t dev_id, a_bool_t * enable,
a_uint32_t * queue)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_igmp_mld_entry_queue_get(dev_id, enable, queue);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set IGMP hardware learning count limit on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[in] enable A_TRUE or A_FALSE
* @param[in] cnt limit count
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_learn_limit_set(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t enable, a_uint32_t cnt)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_mld_learn_limit_set(dev_id, port_id, enable, cnt);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get IGMP hardware learning count limit on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[out] enable A_TRUE or A_FALSE
* @param[out] cnt limit count
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_learn_limit_get(a_uint32_t dev_id, fal_port_t port_id,
a_bool_t * enable, a_uint32_t * cnt)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_mld_learn_limit_get(dev_id, port_id, enable, cnt);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Set IGMP hardware learning count exceed command on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[in] cmd forwarding command
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_learn_exceed_cmd_set(a_uint32_t dev_id, fal_port_t port_id,
fal_fwd_cmd_t cmd)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_mld_learn_exceed_cmd_set(dev_id, port_id, cmd);
HSL_API_UNLOCK;
return rv;
}
/**
* @brief Get IGMP hardware learning count exceed command on a particular port.
* @param[in] dev_id device id
* @param[in] port_id port id
* @param[out] cmd forwarding command
* @return SW_OK or error code
*/
HSL_LOCAL sw_error_t
dess_port_igmp_mld_learn_exceed_cmd_get(a_uint32_t dev_id, fal_port_t port_id,
fal_fwd_cmd_t * cmd)
{
sw_error_t rv;
HSL_API_LOCK;
rv = _dess_port_igmp_mld_learn_exceed_cmd_get(dev_id, port_id, cmd);
HSL_API_UNLOCK;
return rv;
}
sw_error_t
dess_igmp_init(a_uint32_t dev_id)
{
HSL_DEV_ID_CHECK(dev_id);
#ifndef HSL_STANDALONG
{
hsl_api_t *p_api;
SW_RTN_ON_NULL(p_api = hsl_api_ptr_get(dev_id));
p_api->port_igmps_status_set = dess_port_igmps_status_set;
p_api->port_igmps_status_get = dess_port_igmps_status_get;
p_api->igmp_mld_cmd_set = dess_igmp_mld_cmd_set;
p_api->igmp_mld_cmd_get = dess_igmp_mld_cmd_get;
p_api->port_igmp_join_set = dess_port_igmp_mld_join_set;
p_api->port_igmp_join_get = dess_port_igmp_mld_join_get;
p_api->port_igmp_leave_set = dess_port_igmp_mld_leave_set;
p_api->port_igmp_leave_get = dess_port_igmp_mld_leave_get;
p_api->igmp_rp_set = dess_igmp_mld_rp_set;
p_api->igmp_rp_get = dess_igmp_mld_rp_get;
p_api->igmp_entry_creat_set = dess_igmp_mld_entry_creat_set;
p_api->igmp_entry_creat_get = dess_igmp_mld_entry_creat_get;
p_api->igmp_entry_static_set = dess_igmp_mld_entry_static_set;
p_api->igmp_entry_static_get = dess_igmp_mld_entry_static_get;
p_api->igmp_entry_leaky_set = dess_igmp_mld_entry_leaky_set;
p_api->igmp_entry_leaky_get = dess_igmp_mld_entry_leaky_get;
p_api->igmp_entry_v3_set = dess_igmp_mld_entry_v3_set;
p_api->igmp_entry_v3_get = dess_igmp_mld_entry_v3_get;
p_api->igmp_entry_queue_set = dess_igmp_mld_entry_queue_set;
p_api->igmp_entry_queue_get = dess_igmp_mld_entry_queue_get;
p_api->port_igmp_mld_learn_limit_set = dess_port_igmp_mld_learn_limit_set;
p_api->port_igmp_mld_learn_limit_get = dess_port_igmp_mld_learn_limit_get;
p_api->port_igmp_mld_learn_exceed_cmd_set = dess_port_igmp_mld_learn_exceed_cmd_set;
p_api->port_igmp_mld_learn_exceed_cmd_get = dess_port_igmp_mld_learn_exceed_cmd_get;
p_api->igmp_sg_entry_set = dess_igmp_sg_entry_set;
p_api->igmp_sg_entry_clear = dess_igmp_sg_entry_clear;
p_api->igmp_sg_entry_show = dess_igmp_sg_entry_show;
p_api->igmp_sg_entry_query = dess_igmp_sg_entry_query;
}
#endif
return SW_OK;
}
/**
* @}
*/