| /* |
| * Copyright (c) 2012, 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 isis_fdb ISIS_FDB |
| * @{ |
| */ |
| #include "sw.h" |
| #include "hsl.h" |
| #include "hsl_dev.h" |
| #include "hsl_port_prop.h" |
| #include "isis_fdb.h" |
| #include "isis_reg.h" |
| |
| #define ARL_FLUSH_ALL 1 |
| #define ARL_LOAD_ENTRY 2 |
| #define ARL_PURGE_ENTRY 3 |
| #define ARL_FLUSH_ALL_UNLOCK 4 |
| #define ARL_FLUSH_PORT_UNICAST 5 |
| #define ARL_NEXT_ENTRY 6 |
| #define ARL_FIND_ENTRY 7 |
| #define ARL_TRANSFER_ENTRY 8 |
| |
| #define ARL_FIRST_ENTRY 1001 |
| #define ARL_FLUSH_PORT_NO_STATIC 1002 |
| #define ARL_FLUSH_PORT_AND_STATIC 1003 |
| |
| #define ISIS_MAX_FID 4095 |
| #define ISIS_MAX_LEARN_LIMIT_CNT 2047 |
| #define ISIS_MAX_PORT_LEARN_LIMIT_CNT 1023 |
| |
| static sw_error_t |
| _isis_wl_feature_check(a_uint32_t dev_id) |
| { |
| sw_error_t rv; |
| a_uint32_t entry = 0; |
| |
| HSL_REG_FIELD_GET(rv, dev_id, MASK_CTL, 0, DEVICE_ID, |
| (a_uint8_t *) (&entry), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (S17_DEVICE_ID == entry) |
| { |
| return SW_OK; |
| } |
| else |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| } |
| |
| static a_bool_t |
| _isis_fdb_is_zeroaddr(fal_mac_addr_t addr) |
| { |
| a_uint32_t i; |
| |
| for (i = 0; i < 6; i++) |
| { |
| if (addr.uc[i]) |
| { |
| return A_FALSE; |
| } |
| } |
| |
| return A_TRUE; |
| } |
| |
| static void |
| _isis_fdb_fill_addr(fal_mac_addr_t addr, a_uint32_t * reg0, a_uint32_t * reg1) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE0, addr.uc[0], *reg1); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE1, addr.uc[1], *reg1); |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE2, addr.uc[2], *reg0); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE3, addr.uc[3], *reg0); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE4, addr.uc[4], *reg0); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE5, addr.uc[5], *reg0); |
| |
| return; |
| } |
| |
| static sw_error_t |
| _isis_atu_sw_to_hw(a_uint32_t dev_id, const fal_fdb_entry_t * entry, |
| a_uint32_t reg[]) |
| { |
| a_uint32_t port; |
| sw_error_t rv; |
| |
| if (A_TRUE == entry->white_list_en) |
| { |
| rv = _isis_wl_feature_check(dev_id); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, WL_EN, 1, reg[2]); |
| } |
| |
| if (FAL_SVL_FID == entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, 0, reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 1, reg[1]); |
| } |
| else if (ISIS_MAX_FID >= entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, (entry->fid), reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 0, reg[1]); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| if (A_FALSE == entry->portmap_en) |
| { |
| if (A_TRUE != |
| hsl_port_prop_check(dev_id, entry->port.id, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| port = 0x1UL << entry->port.id; |
| } |
| else |
| { |
| if (A_FALSE == |
| hsl_mports_prop_check(dev_id, entry->port.map, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| port = entry->port.map; |
| } |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, DES_PORT, port, reg[1]); |
| |
| if (FAL_MAC_CPY_TO_CPU == entry->dacmd) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, COPY_TO_CPU, 1, reg[2]); |
| } |
| else if (FAL_MAC_RDT_TO_CPU == entry->dacmd) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, 1, reg[2]); |
| } |
| else if (FAL_MAC_FRWRD != entry->dacmd) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| |
| if (A_TRUE == entry->leaky_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 1, reg[2]); |
| } |
| else |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 0, reg[2]); |
| } |
| |
| if (A_TRUE == entry->static_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 15, reg[2]); |
| } |
| else |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 7, reg[2]); |
| } |
| |
| if (FAL_MAC_DROP == entry->sacmd) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, SA_DROP_EN, 1, reg[1]); |
| } |
| else if (FAL_MAC_FRWRD != entry->sacmd) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| |
| if (A_TRUE == entry->mirror_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, MIRROR_EN, 1, reg[1]); |
| } |
| |
| if (A_TRUE == entry->cross_pt_state) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, CROSS_PT, 1, reg[1]); |
| } |
| else |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, CROSS_PT, 0, reg[1]); |
| } |
| |
| if (A_TRUE == entry->da_pri_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_PRI_EN, 1, reg[1]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_PRI, (entry->da_queue & 0x7), |
| reg[1]); |
| } |
| else |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_PRI_EN, 0, reg[1]); |
| } |
| |
| _isis_fdb_fill_addr(entry->addr, ®[0], ®[1]); |
| return SW_OK; |
| } |
| |
| static void |
| _isis_atu_hw_to_sw(const a_uint32_t reg[], fal_fdb_entry_t * entry) |
| { |
| a_uint32_t i, data; |
| |
| aos_mem_zero(entry, sizeof (fal_fdb_entry_t)); |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, AT_SVL_EN, data, reg[1]); |
| if (data) |
| { |
| entry->fid = FAL_SVL_FID; |
| } |
| else |
| { |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_VID, data, reg[2]); |
| entry->fid = data; |
| } |
| |
| entry->dacmd = FAL_MAC_FRWRD; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, COPY_TO_CPU, data, reg[2]); |
| if (1 == data) |
| { |
| entry->dacmd = FAL_MAC_CPY_TO_CPU; |
| } |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, data, reg[2]); |
| if (1 == data) |
| { |
| entry->dacmd = FAL_MAC_RDT_TO_CPU; |
| } |
| |
| entry->sacmd = FAL_MAC_FRWRD; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, SA_DROP_EN, data, reg[1]); |
| if (1 == data) |
| { |
| entry->sacmd = FAL_MAC_DROP; |
| } |
| |
| entry->leaky_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, LEAKY_EN, data, reg[2]); |
| if (1 == data) |
| { |
| entry->leaky_en = A_TRUE; |
| } |
| |
| entry->static_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, data, reg[2]); |
| if (0xf == data) |
| { |
| entry->static_en = A_TRUE; |
| } |
| |
| entry->mirror_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, MIRROR_EN, data, reg[1]); |
| if (1 == data) |
| { |
| entry->mirror_en = A_TRUE; |
| } |
| |
| entry->da_pri_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, AT_PRI_EN, data, reg[1]); |
| if (1 == data) |
| { |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, AT_PRI, data, reg[1]); |
| entry->da_pri_en = A_TRUE; |
| entry->da_queue = data & 0x7; |
| } |
| |
| entry->cross_pt_state = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, CROSS_PT, data, reg[1]); |
| if (1 == data) |
| { |
| entry->cross_pt_state = A_TRUE; |
| } |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, DES_PORT, data, reg[1]); |
| entry->portmap_en = A_TRUE; |
| entry->port.map = data; |
| |
| for (i = 2; i < 6; i++) |
| { |
| entry->addr.uc[i] = (reg[0] >> ((5 - i) << 3)) & 0xff; |
| } |
| |
| for (i = 0; i < 2; i++) |
| { |
| entry->addr.uc[i] = (reg[1] >> ((1 - i) << 3)) & 0xff; |
| } |
| |
| entry->white_list_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, WL_EN, data, reg[2]); |
| if (1 == data) |
| { |
| entry->white_list_en = A_TRUE; |
| } |
| |
| return; |
| } |
| |
| static sw_error_t |
| _isis_atu_down_to_hw(a_uint32_t dev_id, a_uint32_t reg[]) |
| { |
| sw_error_t rv; |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, |
| (a_uint8_t *) (®[0]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, |
| (a_uint8_t *) (®[1]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0, |
| (a_uint8_t *) (®[2]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (®[3]), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_atu_up_to_sw(a_uint32_t dev_id, a_uint32_t reg[]) |
| { |
| sw_error_t rv; |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, |
| (a_uint8_t *) (®[0]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC1, 0, |
| (a_uint8_t *) (®[1]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC2, 0, |
| (a_uint8_t *) (®[2]), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (®[3]), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_commit(a_uint32_t dev_id, a_uint32_t op) |
| { |
| sw_error_t rv; |
| a_uint32_t busy = 1; |
| a_uint32_t full_vio; |
| a_uint32_t i = 2000; |
| a_uint32_t entry = 0; |
| a_uint32_t hwop = op; |
| |
| while (busy && --i) |
| { |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (&entry), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC3, AT_BUSY, busy, entry); |
| aos_udelay(5); |
| } |
| |
| if (0 == i) |
| { |
| printk("%s BUSY\n", __FUNCTION__); |
| return SW_BUSY; |
| } |
| |
| if (ARL_FIRST_ENTRY == op) |
| { |
| hwop = ARL_NEXT_ENTRY; |
| } |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_BUSY, 1, entry); |
| |
| if (ARL_FLUSH_PORT_AND_STATIC == hwop) |
| { |
| hwop = ARL_FLUSH_PORT_UNICAST; |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, FLUSH_ST_EN, 1, entry); |
| } |
| |
| if (ARL_FLUSH_PORT_NO_STATIC == hwop) |
| { |
| hwop = ARL_FLUSH_PORT_UNICAST; |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, FLUSH_ST_EN, 0, entry); |
| } |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_FUNC, hwop, entry); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (&entry), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| busy = 1; |
| i = 2000; |
| while (busy && --i) |
| { |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (&entry), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC3, AT_BUSY, busy, entry); |
| } |
| |
| if (0 == i) |
| { |
| return SW_FAIL; |
| } |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC3, AT_FULL_VIO, full_vio, entry); |
| |
| if (full_vio) |
| { |
| /* must clear AT_FULL_VOI bit */ |
| entry = 0x1000; |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC3, 0, |
| (a_uint8_t *) (&entry), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (ARL_LOAD_ENTRY == hwop) |
| { |
| return SW_FULL; |
| } |
| else if ((ARL_PURGE_ENTRY == hwop) |
| || (ARL_FLUSH_PORT_UNICAST == hwop)) |
| { |
| return SW_NOT_FOUND; |
| } |
| else |
| { |
| return SW_FAIL; |
| } |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_get(a_uint32_t dev_id, fal_fdb_op_t * option, fal_fdb_entry_t * entry, |
| a_uint32_t hwop) |
| { |
| sw_error_t rv; |
| a_uint32_t i, port = 0, status, reg[4] = { 0 }; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if (A_TRUE == option->port_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_PORT_EN, 1, reg[3]); |
| if (A_FALSE == entry->portmap_en) |
| { |
| if (A_TRUE != |
| hsl_port_prop_check(dev_id, entry->port.id, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| port = entry->port.id; |
| } |
| else |
| { |
| if (A_FALSE == |
| hsl_mports_prop_check(dev_id, entry->port.map, |
| HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| status = 0; |
| for (i = 0; i < SW_MAX_NR_PORT; i++) |
| { |
| if ((entry->port.map) & (0x1UL << i)) |
| { |
| if (status) |
| { |
| return SW_BAD_PARAM; |
| } |
| port = i; |
| status = 1; |
| } |
| } |
| } |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_PORT_NUM, port, reg[3]); |
| } |
| |
| if (A_TRUE == option->fid_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_VID_EN, 1, reg[3]); |
| } |
| |
| if (A_TRUE == option->multicast_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_MULTI_EN, 1, reg[3]); |
| } |
| |
| if (FAL_SVL_FID == entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, 0, reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 1, reg[1]); |
| } |
| else if (ISIS_MAX_FID >= entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, entry->fid, reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 0, reg[1]); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| if (ARL_FIRST_ENTRY != hwop) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 0xf, reg[2]); |
| } |
| |
| _isis_fdb_fill_addr(entry->addr, ®[0], ®[1]); |
| |
| rv = _isis_atu_down_to_hw(dev_id, reg); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_fdb_commit(dev_id, hwop); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_atu_up_to_sw(dev_id, reg); |
| SW_RTN_ON_ERROR(rv); |
| |
| _isis_atu_hw_to_sw(reg, entry); |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, status, reg[2]); |
| if ((A_TRUE == _isis_fdb_is_zeroaddr(entry->addr)) |
| && (0 == status)) |
| { |
| if (ARL_NEXT_ENTRY == hwop) |
| { |
| return SW_NO_MORE; |
| } |
| else |
| { |
| return SW_NOT_FOUND; |
| } |
| } |
| else |
| { |
| return SW_OK; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| a_uint32_t reg[4] = { 0 }; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| rv = _isis_atu_sw_to_hw(dev_id, entry, reg); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_atu_down_to_hw(dev_id, reg); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_fdb_commit(dev_id, ARL_LOAD_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag) |
| { |
| sw_error_t rv; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if (FAL_FDB_DEL_STATIC & flag) |
| { |
| rv = _isis_fdb_commit(dev_id, ARL_FLUSH_ALL); |
| } |
| else |
| { |
| rv = _isis_fdb_commit(dev_id, ARL_FLUSH_ALL_UNLOCK); |
| } |
| |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag) |
| { |
| sw_error_t rv; |
| a_uint32_t reg = 0; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if (A_FALSE == hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_PORT_NUM, port_id, reg); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC3, 0, (a_uint8_t *) (®), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (FAL_FDB_DEL_STATIC & flag) |
| { |
| rv = _isis_fdb_commit(dev_id, ARL_FLUSH_PORT_AND_STATIC); |
| } |
| else |
| { |
| rv = _isis_fdb_commit(dev_id, ARL_FLUSH_PORT_NO_STATIC); |
| } |
| |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| a_uint32_t reg0 = 0, reg1 = 0, reg2 = 0; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| _isis_fdb_fill_addr(entry->addr, ®0, ®1); |
| |
| if (FAL_SVL_FID == entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, 0, reg2); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 1, reg1); |
| } |
| else if (ISIS_MAX_FID >= entry->fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, (entry->fid), reg2); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 0, reg1); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0, (a_uint8_t *) (®2), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, (a_uint8_t *) (®1), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (®0), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_fdb_commit(dev_id, ARL_PURGE_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| fal_fdb_op_t option; |
| |
| aos_mem_zero(&option, sizeof (fal_fdb_op_t)); |
| rv = _isis_fdb_get(dev_id, &option, entry, ARL_FIND_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_extend_next(a_uint32_t dev_id, fal_fdb_op_t * option, |
| fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| rv = _isis_fdb_get(dev_id, option, entry, ARL_NEXT_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_extend_first(a_uint32_t dev_id, fal_fdb_op_t * option, |
| fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| rv = _isis_fdb_get(dev_id, option, entry, ARL_FIRST_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_transfer(a_uint32_t dev_id, fal_port_t old_port, fal_port_t new_port, |
| a_uint32_t fid, fal_fdb_op_t * option) |
| { |
| sw_error_t rv; |
| a_uint32_t reg[4] = { 0 }; |
| |
| if (A_TRUE == option->port_en) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| |
| if (A_TRUE == option->fid_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_VID_EN, 1, reg[3]); |
| } |
| |
| if (A_TRUE == option->multicast_en) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_MULTI_EN, 1, reg[3]); |
| } |
| |
| if (FAL_SVL_FID == fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, 0, reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 1, reg[1]); |
| } |
| else if (ISIS_MAX_FID >= fid) |
| { |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_VID, fid, reg[2]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_SVL_EN, 0, reg[1]); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, AT_PORT_NUM, old_port, reg[3]); |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC3, NEW_PORT_NUM, new_port, reg[3]); |
| |
| rv = _isis_atu_down_to_hw(dev_id, reg); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_fdb_commit(dev_id, ARL_TRANSFER_ENTRY); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id, a_bool_t enable) |
| { |
| a_uint32_t data; |
| sw_error_t rv; |
| |
| 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) |
| { |
| data = 1; |
| } |
| else if (A_FALSE == enable) |
| { |
| data = 0; |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_FIELD_SET(rv, dev_id, PORT_LOOKUP_CTL, port_id, LEARN_EN, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t * enable) |
| { |
| a_uint32_t data = 0; |
| sw_error_t rv; |
| |
| 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_LOOKUP_CTL, port_id, LEARN_EN, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (1 == data) |
| { |
| *enable = A_TRUE; |
| } |
| else |
| { |
| *enable = A_FALSE; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable) |
| { |
| a_uint32_t data; |
| sw_error_t rv; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if (A_TRUE == enable) |
| { |
| data = 1; |
| } |
| else if (A_FALSE == enable) |
| { |
| data = 0; |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t * enable) |
| { |
| a_uint32_t data = 0; |
| sw_error_t rv; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (1 == data) |
| { |
| *enable = A_TRUE; |
| } |
| else |
| { |
| *enable = A_FALSE; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time) |
| { |
| a_uint32_t data; |
| sw_error_t rv; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if ((65535 * 7 < *time) || (7 > *time)) |
| { |
| return SW_BAD_PARAM; |
| } |
| data = *time / 7; |
| *time = data * 7; |
| HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t * time) |
| { |
| a_uint32_t data = 0; |
| sw_error_t rv; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME, |
| (a_uint8_t *) (&data), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| *time = data * 7; |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_port_fdb_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 *) (®), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (A_TRUE == enable) |
| { |
| if (ISIS_MAX_PORT_LEARN_LIMIT_CNT < cnt) |
| { |
| return SW_BAD_PARAM; |
| } |
| SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, SA_LEARN_LIMIT_EN, 1, reg); |
| SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, SA_LEARN_CNT, cnt, reg); |
| } |
| else if (A_FALSE == enable) |
| { |
| SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, SA_LEARN_LIMIT_EN, 0, reg); |
| SW_SET_REG_BY_FIELD(PORT_LEARN_LIMIT_CTL, SA_LEARN_CNT, 0, reg); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_port_fdb_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 *) (®), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_GET_FIELD_BY_REG(PORT_LEARN_LIMIT_CTL, SA_LEARN_LIMIT_EN, data, reg); |
| if (data) |
| { |
| SW_GET_FIELD_BY_REG(PORT_LEARN_LIMIT_CTL, SA_LEARN_CNT, data, reg); |
| *enable = A_TRUE; |
| *cnt = data; |
| } |
| else |
| { |
| *enable = A_FALSE; |
| *cnt = 0; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_port_fdb_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, |
| SA_LEARN_LIMIT_DROP_EN, (a_uint8_t *) (&data), |
| sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_port_fdb_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, |
| SA_LEARN_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; |
| } |
| |
| static sw_error_t |
| _isis_fdb_learn_limit_set(a_uint32_t dev_id, a_bool_t enable, a_uint32_t cnt) |
| { |
| sw_error_t rv; |
| a_uint32_t reg = 0; |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, GLOBAL_LEARN_LIMIT_CTL, 0, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (A_TRUE == enable) |
| { |
| if (ISIS_MAX_LEARN_LIMIT_CNT < cnt) |
| { |
| return SW_BAD_PARAM; |
| } |
| SW_SET_REG_BY_FIELD(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_LIMIT_EN, 1, |
| reg); |
| SW_SET_REG_BY_FIELD(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_CNT, cnt, reg); |
| } |
| else if (A_FALSE == enable) |
| { |
| SW_SET_REG_BY_FIELD(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_LIMIT_EN, 0, |
| reg); |
| SW_SET_REG_BY_FIELD(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_CNT, 0, reg); |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_ENTRY_SET(rv, dev_id, GLOBAL_LEARN_LIMIT_CTL, 0, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_learn_limit_get(a_uint32_t dev_id, a_bool_t * enable, |
| a_uint32_t * cnt) |
| { |
| sw_error_t rv; |
| a_uint32_t data, reg = 0; |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, GLOBAL_LEARN_LIMIT_CTL, 0, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_GET_FIELD_BY_REG(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_LIMIT_EN, data, |
| reg); |
| if (data) |
| { |
| SW_GET_FIELD_BY_REG(GLOBAL_LEARN_LIMIT_CTL, GOL_SA_LEARN_CNT, data, |
| reg); |
| *enable = A_TRUE; |
| *cnt = data; |
| } |
| else |
| { |
| *enable = A_FALSE; |
| *cnt = 0; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_learn_exceed_cmd_set(a_uint32_t dev_id, fal_fwd_cmd_t cmd) |
| { |
| sw_error_t rv; |
| a_uint32_t data = 0; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| 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, GLOBAL_LEARN_LIMIT_CTL, 0, |
| GOL_SA_LEARN_LIMIT_DROP_EN, (a_uint8_t *) (&data), |
| sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_learn_exceed_cmd_get(a_uint32_t dev_id, fal_fwd_cmd_t * cmd) |
| { |
| sw_error_t rv; |
| a_uint32_t data = 0; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| HSL_REG_FIELD_GET(rv, dev_id, GLOBAL_LEARN_LIMIT_CTL, 0, |
| GOL_SA_LEARN_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; |
| } |
| |
| #define ISIS_RESV_ADDR_NUM 32 |
| #define RESV_ADDR_TBL0_ADDR 0x3c000 |
| #define RESV_ADDR_TBL1_ADDR 0x3c004 |
| #define RESV_ADDR_TBL2_ADDR 0x3c008 |
| |
| static void |
| _isis_resv_addr_parse(const a_uint32_t reg[], fal_mac_addr_t * addr) |
| { |
| a_uint32_t i; |
| |
| for (i = 2; i < 6; i++) |
| { |
| addr->uc[i] = (reg[0] >> ((5 - i) << 3)) & 0xff; |
| } |
| |
| for (i = 0; i < 2; i++) |
| { |
| addr->uc[i] = (reg[1] >> ((1 - i) << 3)) & 0xff; |
| } |
| } |
| |
| static sw_error_t |
| _isis_resv_atu_sw_to_hw(a_uint32_t dev_id, fal_fdb_entry_t * entry, |
| a_uint32_t reg[]) |
| { |
| a_uint32_t port; |
| |
| if (A_FALSE == entry->portmap_en) |
| { |
| if (A_TRUE != |
| hsl_port_prop_check(dev_id, entry->port.id, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| port = 0x1UL << entry->port.id; |
| } |
| else |
| { |
| if (A_FALSE == |
| hsl_mports_prop_check(dev_id, entry->port.map, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| port = entry->port.map; |
| } |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_DES_PORT, port, reg[1]); |
| |
| if (FAL_MAC_CPY_TO_CPU == entry->dacmd) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_COPY_TO_CPU, 1, reg[1]); |
| } |
| else if (FAL_MAC_RDT_TO_CPU == entry->dacmd) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_REDRCT_TO_CPU, 1, reg[1]); |
| } |
| else if (FAL_MAC_FRWRD != entry->dacmd) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| |
| if (FAL_MAC_FRWRD != entry->sacmd) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| |
| if (A_TRUE == entry->leaky_en) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_LEAKY_EN, 1, reg[1]); |
| } |
| else |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_LEAKY_EN, 0, reg[1]); |
| } |
| |
| if (A_TRUE != entry->static_en) |
| { |
| return SW_NOT_SUPPORTED; |
| } |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL2, RESV_STATUS, 1, reg[2]); |
| |
| if (A_TRUE == entry->mirror_en) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_MIRROR_EN, 1, reg[1]); |
| } |
| |
| if (A_TRUE == entry->cross_pt_state) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_CROSS_PT, 1, reg[1]); |
| } |
| |
| if (A_TRUE == entry->da_pri_en) |
| { |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_PRI_EN, 1, reg[1]); |
| SW_SET_REG_BY_FIELD(RESV_ADDR_TBL1, RESV_PRI, (entry->da_queue & 0x7), |
| reg[1]); |
| } |
| |
| _isis_fdb_fill_addr(entry->addr, ®[0], ®[1]); |
| return SW_OK; |
| } |
| |
| static void |
| _isis_resv_atu_hw_to_sw(const a_uint32_t reg[], fal_fdb_entry_t * entry) |
| { |
| a_uint32_t data; |
| |
| aos_mem_zero(entry, sizeof (fal_fdb_entry_t)); |
| |
| entry->fid = FAL_SVL_FID; |
| |
| entry->dacmd = FAL_MAC_FRWRD; |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_COPY_TO_CPU, data, reg[1]); |
| if (1 == data) |
| { |
| entry->dacmd = FAL_MAC_CPY_TO_CPU; |
| } |
| |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_REDRCT_TO_CPU, data, reg[1]); |
| if (1 == data) |
| { |
| entry->dacmd = FAL_MAC_RDT_TO_CPU; |
| } |
| |
| entry->sacmd = FAL_MAC_FRWRD; |
| |
| entry->leaky_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_LEAKY_EN, data, reg[1]); |
| if (1 == data) |
| { |
| entry->leaky_en = A_TRUE; |
| } |
| |
| entry->static_en = A_TRUE; |
| |
| entry->mirror_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_MIRROR_EN, data, reg[1]); |
| if (1 == data) |
| { |
| entry->mirror_en = A_TRUE; |
| } |
| |
| entry->da_pri_en = A_FALSE; |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_PRI_EN, data, reg[1]); |
| if (1 == data) |
| { |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_PRI, data, reg[1]); |
| entry->da_pri_en = A_TRUE; |
| entry->da_queue = data & 0x7; |
| } |
| |
| entry->cross_pt_state = A_FALSE; |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_CROSS_PT, data, reg[1]); |
| if (1 == data) |
| { |
| entry->cross_pt_state = A_TRUE; |
| } |
| |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL1, RESV_DES_PORT, data, reg[1]); |
| entry->portmap_en = A_TRUE; |
| entry->port.map = data; |
| |
| _isis_resv_addr_parse(reg, &(entry->addr)); |
| return; |
| } |
| |
| static sw_error_t |
| _isis_fdb_resv_commit(a_uint32_t dev_id, fal_fdb_entry_t * entry, a_uint32_t op, |
| a_uint32_t * empty) |
| { |
| a_uint32_t index, addr, data, tbl[3] = { 0 }; |
| sw_error_t rv; |
| fal_mac_addr_t mac_tmp; |
| |
| *empty = ISIS_RESV_ADDR_NUM; |
| for (index = 0; index < ISIS_RESV_ADDR_NUM; index++) |
| { |
| addr = RESV_ADDR_TBL2_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[2])), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL2, RESV_STATUS, data, tbl[2]); |
| if (data) |
| { |
| addr = RESV_ADDR_TBL0_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[0])), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| addr = RESV_ADDR_TBL1_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[1])), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| _isis_resv_addr_parse(tbl, &mac_tmp); |
| if (!aos_mem_cmp |
| ((void *) &(entry->addr), (void *) &mac_tmp, |
| sizeof (fal_mac_addr_t))) |
| { |
| if (ARL_PURGE_ENTRY == op) |
| { |
| addr = RESV_ADDR_TBL2_ADDR + (index << 4); |
| tbl[2] = 0; |
| HSL_REG_ENTRY_GEN_SET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[2])), |
| sizeof (a_uint32_t)); |
| return rv; |
| } |
| else if (ARL_LOAD_ENTRY == op) |
| { |
| return SW_ALREADY_EXIST; |
| } |
| else if (ARL_FIND_ENTRY == op) |
| { |
| _isis_resv_atu_hw_to_sw(tbl, entry); |
| return SW_OK; |
| } |
| } |
| } |
| else |
| { |
| *empty = index; |
| } |
| } |
| |
| return SW_NOT_FOUND; |
| } |
| |
| static sw_error_t |
| _isis_fdb_resv_add(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| a_uint32_t i, empty, addr, tbl[3] = { 0 }; |
| |
| rv = _isis_resv_atu_sw_to_hw(dev_id, entry, tbl); |
| SW_RTN_ON_ERROR(rv); |
| |
| rv = _isis_fdb_resv_commit(dev_id, entry, ARL_LOAD_ENTRY, &empty); |
| if (SW_ALREADY_EXIST == rv) |
| { |
| return rv; |
| } |
| |
| if (ISIS_RESV_ADDR_NUM == empty) |
| { |
| return SW_NO_RESOURCE; |
| } |
| |
| for (i = 0; i < 3; i++) |
| { |
| addr = RESV_ADDR_TBL0_ADDR + (empty << 4) + (i << 2); |
| HSL_REG_ENTRY_GEN_SET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[i])), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_resv_del(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| a_uint32_t empty; |
| |
| rv = _isis_fdb_resv_commit(dev_id, entry, ARL_PURGE_ENTRY, &empty); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_resv_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| a_uint32_t empty; |
| |
| rv = _isis_fdb_resv_commit(dev_id, entry, ARL_FIND_ENTRY, &empty); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_resv_iterate(a_uint32_t dev_id, a_uint32_t * iterator, |
| fal_fdb_entry_t * entry) |
| { |
| a_uint32_t index, addr, data, tbl[3] = { 0 }; |
| sw_error_t rv; |
| |
| if ((NULL == iterator) || (NULL == entry)) |
| { |
| return SW_BAD_PTR; |
| } |
| |
| if (ISIS_RESV_ADDR_NUM < *iterator) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| for (index = *iterator; index < ISIS_RESV_ADDR_NUM; index++) |
| { |
| addr = RESV_ADDR_TBL2_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[2])), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_GET_FIELD_BY_REG(RESV_ADDR_TBL2, RESV_STATUS, data, tbl[2]); |
| if (data) |
| { |
| addr = RESV_ADDR_TBL0_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[0])), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| addr = RESV_ADDR_TBL1_ADDR + (index << 4); |
| HSL_REG_ENTRY_GEN_GET(rv, dev_id, addr, sizeof (a_uint32_t), |
| (a_uint8_t *) (&(tbl[1])), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| _isis_resv_atu_hw_to_sw(tbl, entry); |
| break; |
| } |
| } |
| |
| if (ISIS_RESV_ADDR_NUM == index) |
| { |
| return SW_NO_MORE; |
| } |
| |
| *iterator = index + 1; |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_port_learn_static_set(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t enable) |
| { |
| a_uint32_t data; |
| sw_error_t rv; |
| |
| 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) |
| { |
| data = 0xf; |
| } |
| else if (A_FALSE == enable) |
| { |
| data = 0x7; |
| } |
| else |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| HSL_REG_FIELD_SET(rv, dev_id, PORT_LEARN_LIMIT_CTL, port_id, |
| SA_LEARN_STATUS, (a_uint8_t *) (&data), |
| sizeof (a_uint32_t)); |
| return rv; |
| } |
| |
| static sw_error_t |
| _isis_fdb_port_learn_static_get(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t * enable) |
| { |
| a_uint32_t data = 0; |
| sw_error_t rv; |
| |
| 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, |
| SA_LEARN_STATUS, (a_uint8_t *) (&data), |
| sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| if (0xf == data) |
| { |
| *enable = A_TRUE; |
| } |
| else |
| { |
| *enable = A_FALSE; |
| } |
| |
| return SW_OK; |
| } |
| |
| static sw_error_t |
| _isis_fdb_port_update(a_uint32_t dev_id, a_uint32_t fid, fal_mac_addr_t * addr, fal_port_t port_id, a_uint32_t op) |
| { |
| sw_error_t rv; |
| fal_fdb_entry_t entry; |
| fal_fdb_op_t option; |
| a_uint32_t reg, port; |
| |
| HSL_DEV_ID_CHECK(dev_id); |
| |
| if (FAL_SVL_FID < fid) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU)) |
| { |
| return SW_BAD_PARAM; |
| } |
| |
| aos_mem_zero(&option, sizeof(fal_fdb_op_t)); |
| aos_mem_copy(&(entry.addr), addr, sizeof(fal_mac_addr_t)); |
| entry.fid = fid & 0xffff; |
| rv = _isis_fdb_get(dev_id, &option, &entry, ARL_FIND_ENTRY); |
| SW_RTN_ON_ERROR(rv); |
| |
| HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC1, 0, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| SW_RTN_ON_ERROR(rv); |
| |
| SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC1, DES_PORT, port, reg); |
| if (op) |
| { |
| port |= (0x1 << port_id); |
| } |
| else |
| { |
| port &= (~(0x1 << port_id)); |
| } |
| SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, DES_PORT, port, reg); |
| HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, |
| (a_uint8_t *) (®), sizeof (a_uint32_t)); |
| |
| rv = _isis_fdb_commit(dev_id, ARL_LOAD_ENTRY); |
| return rv; |
| } |
| |
| /** |
| * @brief Add a Fdb entry |
| * @param[in] dev_id device id |
| * @param[in] entry fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_add(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Delete all Fdb entries |
| * @details Comments: |
| * If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb |
| * entries otherwise only delete dynamic entries. |
| * @param[in] dev_id device id |
| * @param[in] flag delete operation option |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_del_all(dev_id, flag); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Delete Fdb entries on a particular port |
| * @details Comments: |
| * If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb |
| * entries otherwise only delete dynamic entries. |
| * @param[in] dev_id device id |
| * @param[in] port_id port id |
| * @param[in] flag delete operation option |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_del_by_port(dev_id, port_id, flag); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Delete a particular Fdb entry through mac address |
| * @details Comments: |
| * Only addr field in entry is meaning. For IVL learning vid or fid field |
| * also is meaning. |
| * @param[in] dev_id device id |
| * @param[in] entry fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_del_by_mac(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Find a particular Fdb entry from device through mac address. |
| * @details Comments: |
| For input parameter only addr field in entry is meaning. |
| * @param[in] dev_id device id |
| * @param[in] entry fdb entry |
| * @param[out] entry fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_find(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get next Fdb entry from a particular device |
| * @param[in] dev_id device id |
| * @param[in] option next operation options |
| * @param[out] entry fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_extend_next(a_uint32_t dev_id, fal_fdb_op_t * option, |
| fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_extend_next(dev_id, option, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get first Fdb entry from a particular device |
| * @param[in] dev_id device id |
| * @param[in] option first operation options |
| * @param[out] entry fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_extend_first(a_uint32_t dev_id, fal_fdb_op_t * option, |
| fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_extend_first(dev_id, option, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Transfer fdb entries port information on a particular device. |
| * @param[in] dev_id device id |
| * @param[in] old_port source port id |
| * @param[in] new_port destination port id |
| * @param[in] fid filter database id |
| * @param[in] option transfer operation options |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_transfer(a_uint32_t dev_id, fal_port_t old_port, fal_port_t new_port, |
| a_uint32_t fid, fal_fdb_op_t * option) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_transfer(dev_id, old_port, new_port, fid, option); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address learning status on a particular port. |
| * @details Comments: |
| * This operation will enable or disable dynamic address learning |
| * feature on a particular port. |
| * @param[in] dev_id device id |
| * @param[in] port_id port id |
| * @param[in] enable enable or disable |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id, a_bool_t enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_learn_set(dev_id, port_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address learning 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 |
| isis_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t * enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_learn_get(dev_id, port_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address aging status on particular device. |
| * @details Comments: |
| * This operation will enable or disable dynamic address aging |
| * feature on particular device. |
| * @param[in] dev_id device id |
| * @param[in] enable enable or disable |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_age_ctrl_set(dev_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address aging status on particular device. |
| * @param[in] dev_id device id |
| * @param[in] enable enable or disable |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t * enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_age_ctrl_get(dev_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address aging time on a particular device. |
| * @details Comments: |
| * This operation will set dynamic address aging time on a particular device. |
| * The unit of time is second. Because different device has differnet |
| * hardware granularity function will return actual time in hardware. |
| * @param[in] dev_id device id |
| * @param time aging time |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_age_time_set(dev_id, time); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address aging time on a particular device. |
| * @param[in] dev_id device id |
| * @param[out] time aging time |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t * time) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_age_time_get(dev_id, time); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address 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 |
| isis_port_fdb_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 = _isis_port_fdb_learn_limit_set(dev_id, port_id, enable, cnt); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address 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 |
| isis_port_fdb_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 = _isis_port_fdb_learn_limit_get(dev_id, port_id, enable, cnt); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address 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 |
| isis_port_fdb_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 = _isis_port_fdb_learn_exceed_cmd_set(dev_id, port_id, cmd); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address 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 |
| isis_port_fdb_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 = _isis_port_fdb_learn_exceed_cmd_get(dev_id, port_id, cmd); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address learning count limit on a particular device. |
| * @param[in] dev_id device 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 |
| isis_fdb_learn_limit_set(a_uint32_t dev_id, a_bool_t enable, a_uint32_t cnt) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_learn_limit_set(dev_id, enable, cnt); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address learning count limit on a particular device. |
| * @param[in] dev_id device 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 |
| isis_fdb_learn_limit_get(a_uint32_t dev_id, a_bool_t * enable, a_uint32_t * cnt) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_learn_limit_get(dev_id, enable, cnt); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set dynamic address learning count exceed command on a particular device. |
| * @param[in] dev_id device id |
| * @param[in] cmd forwarding command |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_learn_exceed_cmd_set(a_uint32_t dev_id, fal_fwd_cmd_t cmd) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_learn_exceed_cmd_set(dev_id, cmd); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get dynamic address learning count exceed 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 |
| isis_fdb_learn_exceed_cmd_get(a_uint32_t dev_id, fal_fwd_cmd_t * cmd) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_learn_exceed_cmd_get(dev_id, cmd); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Add a particular reserve Fdb entry |
| * @param[in] dev_id device id |
| * @param[in] entry reserve fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_resv_add(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_resv_add(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Delete a particular reserve Fdb entry through mac address |
| * @param[in] dev_id device id |
| * @param[in] entry reserve fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_resv_del(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_resv_del(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Find a particular reserve Fdb entry through mac address |
| * @param[in] dev_id device id |
| * @param[in] entry reserve fdb entry |
| * @param[out] entry reserve fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_resv_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_resv_find(dev_id, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Iterate all reserve fdb entries on a particular device. |
| * @param[in] dev_id device id |
| * @param[in] iterator reserve fdb entry index if it's zero means get the first entry |
| * @param[out] iterator next valid fdb entry index |
| * @param[out] entry reserve fdb entry |
| * @return SW_OK or error code |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_resv_iterate(a_uint32_t dev_id, a_uint32_t * iterator, |
| fal_fdb_entry_t * entry) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_resv_iterate(dev_id, iterator, entry); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Set the static status of fdb entries which learned by hardware on a particular port. |
| * @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 |
| isis_fdb_port_learn_static_set(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_learn_static_set(dev_id, port_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Get the static status of fdb entries which learned by hardware 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 |
| isis_fdb_port_learn_static_get(a_uint32_t dev_id, fal_port_t port_id, |
| a_bool_t * enable) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_learn_static_get(dev_id, port_id, enable); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Add a port to an exsiting entry |
| * @param[in] dev_id device id |
| * @param[in] fid filtering database id |
| * @param[in] addr MAC address |
| * @param[in] port_id port id |
| * @return SW_OK or error code, If entry not exist will return error. |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_port_add(a_uint32_t dev_id, a_uint32_t fid, fal_mac_addr_t * addr, fal_port_t port_id) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_update(dev_id, fid, addr, port_id, 1); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| /** |
| * @brief Delete a port from an exsiting entry |
| * @param[in] dev_id device id |
| * @param[in] fid filtering database id |
| * @param[in] addr MAC address |
| * @param[in] port_id port id |
| * @return SW_OK or error code, If entry not exist will return error. |
| */ |
| HSL_LOCAL sw_error_t |
| isis_fdb_port_del(a_uint32_t dev_id, a_uint32_t fid, fal_mac_addr_t * addr, fal_port_t port_id) |
| { |
| sw_error_t rv; |
| |
| HSL_API_LOCK; |
| rv = _isis_fdb_port_update(dev_id, fid, addr, port_id, 0); |
| HSL_API_UNLOCK; |
| return rv; |
| } |
| |
| sw_error_t |
| isis_fdb_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->fdb_add = isis_fdb_add; |
| p_api->fdb_del_all = isis_fdb_del_all; |
| p_api->fdb_del_by_port = isis_fdb_del_by_port; |
| p_api->fdb_del_by_mac = isis_fdb_del_by_mac; |
| p_api->fdb_extend_first = isis_fdb_extend_first; |
| p_api->fdb_extend_next = isis_fdb_extend_next; |
| p_api->fdb_find = isis_fdb_find; |
| p_api->port_learn_set = isis_fdb_port_learn_set; |
| p_api->port_learn_get = isis_fdb_port_learn_get; |
| p_api->age_ctrl_set = isis_fdb_age_ctrl_set; |
| p_api->age_ctrl_get = isis_fdb_age_ctrl_get; |
| p_api->age_time_set = isis_fdb_age_time_set; |
| p_api->age_time_get = isis_fdb_age_time_get; |
| p_api->fdb_extend_next = isis_fdb_extend_next; |
| p_api->fdb_extend_first = isis_fdb_extend_first; |
| p_api->fdb_transfer = isis_fdb_transfer; |
| p_api->port_fdb_learn_limit_set = isis_port_fdb_learn_limit_set; |
| p_api->port_fdb_learn_limit_get = isis_port_fdb_learn_limit_get; |
| p_api->port_fdb_learn_exceed_cmd_set = isis_port_fdb_learn_exceed_cmd_set; |
| p_api->port_fdb_learn_exceed_cmd_get = isis_port_fdb_learn_exceed_cmd_get; |
| p_api->fdb_learn_limit_set = isis_fdb_learn_limit_set; |
| p_api->fdb_learn_limit_get = isis_fdb_learn_limit_get; |
| p_api->fdb_learn_exceed_cmd_set = isis_fdb_learn_exceed_cmd_set; |
| p_api->fdb_learn_exceed_cmd_get = isis_fdb_learn_exceed_cmd_get; |
| p_api->fdb_resv_add = isis_fdb_resv_add; |
| p_api->fdb_resv_del = isis_fdb_resv_del; |
| p_api->fdb_resv_find = isis_fdb_resv_find; |
| p_api->fdb_resv_iterate = isis_fdb_resv_iterate; |
| p_api->fdb_port_learn_static_set = isis_fdb_port_learn_static_set; |
| p_api->fdb_port_learn_static_get = isis_fdb_port_learn_static_get; |
| p_api->fdb_port_add = isis_fdb_port_add; |
| p_api->fdb_port_del = isis_fdb_port_del; |
| } |
| #endif |
| |
| return SW_OK; |
| } |
| |
| /** |
| * @} |
| */ |
| |