DAL

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using JYK;

namespace Database
{
    public class DAL
    {
        #region 运行查询语句返回记录(DataSet、DataTable、DataRow、String[]、String)

        public static DataSet RunSqlDataSet(string sql)
        {
            string msg = "";
            return RunSqlDataSet(sql, out msg);
        }

        /// <summary>
        /// 运行SQL查询语句 返回DataSet。可以传入多条查询语句,返回的DataSet里会有多个DataTable
        /// </summary>
        /// <param name="SQL">查询语句。比如select * from tableName</param>
        #region 函数实现 — — RunSqlDataSet
        public static DataSet RunSqlDataSet(string sql, out string ErrorMsg)
        {
            ErrorMsg = "";
            //设置DataAdapter
            DbDataAdapter da = Factory.CreateDataAdapter(sql);
            try
            {
                DataSet DS = new DataSet();
                da.Fill(DS);
                return DS;
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlDataSet", sql, ex.Message);    //处理错误
                ErrorMsg = ex.Message + "<BR>RunSqlDataSet_SQL:" + sql;
                return null;
            }
            finally
            {
                //关闭数据库,销毁实例
                Factory.DbDataAdapterDispose(da);

            }
        }
        #endregion


        public static DataTable RunSqlDataTable(string sql)
        {
            string msg = "";
            return RunSqlDataTable(sql, out msg);

        }

        /// <summary>
        /// 运行SQL查询语句 返回DataTable。
        /// </summary>
        /// <param name="SQL">查询语句。比如select * from tableName</param>
        ///
        #region 函数实现 — — RunSqlDataTable
        public static DataTable RunSqlDataTable(string sql, out string ErrorMsg)
        {
            ErrorMsg = "";
            //设置DataAdapter
            DbDataAdapter da = Factory.CreateDataAdapter(sql);
            try
            {
                DataTable DT = new DataTable();
                da.Fill(DT);
                return DT;
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlDataTable", sql, ex.Message);    //处理错误
                ErrorMsg = ex.Message + "<BR>RunSqlDataSet_SQL:" + sql;
                return null;
            }
            finally
            {
                //关闭数据库,销毁实例
                Factory.DbDataAdapterDispose(da);
            }
        }
        #endregion


        /// <summary>
        /// 运行SQl语句返回第一条记录。返回DataRow
        /// </summary>
        /// <param name="SQL">查询语句。比如select * from tableName</param>
        ///
        #region 函数实现 — — RunSqlDataRow
        public static DataRow RunSqlDataRow(string sql)
        {
            //设置DataAdapter
            DbDataAdapter da = Factory.CreateDataAdapter(sql);
            try
            {
                DataTable DT = new DataTable();
                da.Fill(DT);
                if (DT.Rows.Count > 0)
                    return DT.Rows[0];
                else
                    return null;
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlDataRow", sql, ex.Message);    //处理错误
                return null;
            }
            finally
            {
                //关闭数据库,销毁实例
                Factory.DbDataAdapterDispose(da);
            }

        }
        #endregion


        /// <summary>
        /// 运行SQl语句返回第一条记录的数组。返回字符串数组
        /// </summary>
        /// <param name="SQL">查询语句。比如select top 1 * from tableName</param>
        ///
        #region 函数实现 — — RunSqlStrings
        public static string[] RunSqlStrings(string sql)
        {
            //传入查询语句,返回第一条记录的字符串数组
            //设置command
            DbCommand cm = Factory.CreateCommand(sql);

            try
            {
                cm.Connection.Open();

                DbDataReader r = cm.ExecuteReader(CommandBehavior.SingleRow);
                if (r.Read())
                {
                    int ArrLength = r.FieldCount;

                    string[] strValue = new string[ArrLength];
                    for (int i = 0; i < ArrLength; i++)
                        strValue[i] = r.GetValue(i).ToString();
                    return strValue;
                }
                else
                {
                    r.Close();
                    return null;
                }
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlStrings", sql, ex.Message);    //处理错误
                return null;
            }
            finally
            {
                cm.Connection.Close();
                cm.Connection.Dispose();
                cm.Dispose();

            }
        }
        #endregion

        /// <summary>
        /// 运行SQl语句返回每一条记录的第一个字段的数组。返回字符串数组
        /// </summary>
        /// <param name="SQL">查询语句。比如select myName from tableName</param>
        ///
        #region 函数实现 — — RunSqlStringsByRow
        public static string[] RunSqlStringsByRow(string sql)
        {

            //传入查询语句,每一条记录的第一个字段的数组。返回字符串数组
            //设置command
            DbCommand cm = Factory.CreateCommand(sql);

            try
            {
                cm.Connection.Open();

                DbDataReader r = cm.ExecuteReader();

                System.Collections.Generic.List<string> list = new List<string>();
                while (r.Read())
                    list.Add(r[0].ToString());

                return list.ToArray();

            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlStringsByRow", sql, ex.Message);    //处理错误
                return null;
            }
            finally
            {
                cm.Connection.Close();
                cm.Connection.Dispose();
                cm.Dispose();

            }
        }
        #endregion

        /// <summary>
        /// 运行SQl语句返回第一条记录的第一列的值。
        /// </summary>
        /// <param name="SQL">查询语句。比如select top 1 ID from tableName where userName='aa'。会返回ID的内容</param>
        ///
        #region 函数实现 — — RunSqlGetID
        public static string RunSqlGetID(string sql)
        {
            //设置command
            DbCommand cm = Factory.CreateCommand(sql);

            try
            {
                cm.Connection.Open();

                DbDataReader r = cm.ExecuteReader(CommandBehavior.SingleRow);
                if (r.Read())
                    return r.GetValue(0).ToString();
                else
                    return null;
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlGetID", sql, ex.Message);    //处理错误
                return null;
            }
            finally
            {
                cm.Connection.Close();
                cm.Connection.Dispose();
                cm.Dispose();
            }
        }
        #endregion

        #endregion
        #region 运行查询语句不返回记录集(无返回记录、检查持否存在指定的记录)
        /// <summary>
        /// 运行SQL查询语句,不返回记录集。用于添加、修改、删除等操作
        /// </summary>
        /// <param name="SQL">查询语句。比如insert into tableName 、update tableName</param>
        ///
        #region 函数实现 — — RunSql
        public static void RunSql(string sql)
        {
            //设置command
            DbCommand cm = Factory.CreateCommand(sql);

            try
            {
                cm.Connection.Open();
                cm.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSql", sql, ex.Message);    //处理错误
            }
            finally
            {
                cm.Connection.Close();
                cm.Connection.Dispose();
                cm.Dispose();
            }
        }
        #endregion

        /// <summary>
        /// 执行一条SQL语句,看是否能查到记录 有:返回true;没有返回false,用于判断是否重名
        /// </summary>
        /// <param name="SQL">查询语句。比如select ID from tableName where userName='aa'</param>
        ///
        #region 函数实现 — — RunSqlExists
        public static bool RunSqlExists(string sql)
        {
            //设置command
            DbCommand cm = Factory.CreateCommand(sql);

            try
            {
                if (cm.Connection.State == ConnectionState.Broken || cm.Connection.State == ConnectionState.Closed)
                    cm.Connection.Open();

                DbDataReader r = cm.ExecuteReader(CommandBehavior.CloseConnection);
                if (r.HasRows)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                WriteLog.SetErrorMsg("RunSqlDataSet", sql, ex.Message);    //处理错误
                return true;
            }
            finally
            {
                cm.Connection.Close();
                cm.Connection.Dispose();
                cm.Dispose();
            }
        }
        #endregion

        #endregion
        #region 查询语句的方式添加、修改数据

        /// <summary>
        /// 添加记录。传入表名,字段数组,值数组,返回新生成记录的ID
        /// </summary>
        /// <param name="TableName">要添加记录的表的名称</param>
        /// <param name="ziduan">字段名数组</param>
        /// <param name="msg">字段对应的值的数组</param>
        /// <returns></returns>
        public static string InsertDataStr(string TableName, string[] columns, string[] msg)
        {
            //添加数据    返回新添加的ID
            System.Text.StringBuilder SQL = new System.Text.StringBuilder(300);
            SQL.Append("insert into ");                    //insert into
            SQL.Append(TableName);
            SQL.Append(" (");
            int i;
            for (i = 0; i < columns.Length - 1; i++)        //字段
            {
                SQL.Append(columns[i]);
                SQL.Append(",");
            }
            SQL.Append(columns[i]);
            SQL.Append(")  values ('");

            for (i = 0; i < columns.Length - 1; i++)
            {
                SQL.Append(msg[i]);
                SQL.Append("','");
            }
            SQL.Append(msg[i]);
            if (WebConfig.DataBaseType() == 1)
                SQL.Append("')  select scope_identity() as a1");
            else
                SQL.Append("')");

            string re = RunSqlGetID(SQL.ToString());
            SQL.Length = 1;
            if (re == null)
                return "-1";
            else
                return re;
        }

        /// <summary>
        /// 修改记录。传入表名,字段数组,值数组
        /// </summary>
        /// <param name="TableName">要修改记录的表的名称</param>
        /// <param name="ziduan">字段名数组</param>
        /// <param name="msg">字段对应的值的数组</param>
        /// <param name="tiaojian">条件 ,加在where 后面的语句</param>
        /// <returns></returns>
        public static bool UpdateData(string TableName, string[] cloumns, string[] msg, string myWhere)
        {
            System.Text.StringBuilder SQL = new System.Text.StringBuilder(300);
            SQL.Append("update ");                    //update
            SQL.Append(TableName);
            SQL.Append(" set ");
            int i;
            for (i = 0; i < cloumns.Length - 1; i++)
            {
                SQL.Append(cloumns[i]);                    //update
                SQL.Append("='");
                SQL.Append(msg[i]);
                SQL.Append("',");
            }
            SQL.Append(cloumns[i]);                    //update
            SQL.Append("='");
            SQL.Append(msg[i]);
            SQL.Append("' where ");
            SQL.Append(myWhere);

            RunSql(SQL.ToString());
            return true;
        }
        #endregion
    }
}

static int _dalErpsPortStateSet(int instanceNo, user_port_list *uplist, int state) { return hiMstpPortStateSet(instanceNo, uplist, state); } static int _dalErpsPortConfigHandle(dal_ado_t *adoi, void *handler, char *key) { UINT32 instanceNo = 0; user_port up = {}; user_port_list uplistLocal = {}; int state = 0; DAL_ERPS_KEY_PORT_PARSE(key, up, instanceNo); if (PFM_ERR_C_OK != uplist_init(&uplistLocal)) { return ERR_NO_MEMORY; } if (UP_IS_LOCAL(up) && !UP_IS_STACK(up) /*&& !UP_IS_PLP(up)*/) { UP_LIST_ADD(&uplistLocal, up); DBG("unit:%d index:%d", UP_UNIT(up), UP_PORT(up)); } if (DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { /* do nothing */ } else { DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_ERPS_K_PORT_F_STATE)) { dalAdoiGetEntryI32(adoi, DAL_ERPS_K_PORT_PREFIX, &state); } } APPL_IF_ERR_RET(_dalErpsPortStateSet(instanceNo, &uplistLocal, state)); DBG("_dalErpsPortConfigHandle up:%d instance:%d state %d\n",UP_INDEX(up), instanceNo, state); } uplist_free(&uplistLocal); return ERR_NO_ERROR; } static int _dalErpsPortCfmHandle(dal_ado_t *adoi, void *handler, char *key) { UINT32 ring = 0; user_port up = {}; int enable = 0; int cvlan = 0; int send = 0; int flowId = 0; UINT32 packetId = 0; DAL_ERPS_KEY_PORT_CFM_PARSE(key, up, ring); if (!UP_IS_LOCAL(up) || UP_IS_STACK(up)) { DBG("invalid up: unit:%d index:%d", UP_UNIT(up), UP_PORT(up)); return ERR_NO_ERROR; } if (DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { /* do nothing */ } else { DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_ERPS_K_PORT_CFM_F_ENABLE)) { dalAdoiGetEntryI32(adoi, DAL_ERPS_K_PORT_CFM_PREFIX, &enable); APPL_IF_ERR_RET(dalErpsPort2FlowId(up, &flowId)); return hiErpsOamEntrySet(flowId, enable); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_ERPS_K_PORT_CFM_F_CVLAN)) { dalAdoiGetEntryI32(adoi, DAL_ERPS_K_PORT_CFM_PREFIX, &cvlan); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_ERPS_K_PORT_CFM_F_SEND)) { dalAdoiGetEntryI32(adoi, DAL_ERPS_K_PORT_CFM_PREFIX, &send); } } if (send) { if (!dalErpsCfmPortInUse(up)) { /* send时,hw会分配一个packetId,后续remove时需要使用该id去remove,因此此处的packetId需要记录下来, 同时flowid也一并分配好,将 端口<->packetId<->flowId 对应关系绑定好,方便后续统一管理 */ APPL_IF_ERR_RET(dalErpsFlowIdAllocByPort(up, &flowId)); APPL_IF_ERR_RET(hiErpsOamCcmTxFlowSend(up, cvlan, &packetId)); APPL_IF_ERR_RET(dalErpsPortPacketIdSet(up, packetId)); APPL_IF_ERR_RET(hiErpsTpclEntrySet(up, flowId, TRUE)); } } else { if (dalErpsCfmPortInUse(up)) { APPL_IF_ERR_RET(dalErpsPort2PacketId(up, &packetId)); APPL_IF_ERR_RET(dalErpsPort2FlowId(up, &flowId)); APPL_IF_ERR_RET(hiErpsOamCcmPacketRemove(up, packetId)); APPL_IF_ERR_RET(dalErpsCfmPortReset(up)); APPL_IF_ERR_RET(hiErpsTpclEntrySet(up, flowId, FALSE)); } } } return ERR_NO_ERROR; } /*! *\fn _dalErpsHandler *\brief erps dmp dal handler *\details * *\param[in] * * * *\param[out] * *\return int *\retval ERR_NO_ERROR 成功 * other 失败 * *\note * */ static int _dalErpsHandler(IN dal_ado_t *adoi, IN dal_attr *attr) { int ret = ERR_NO_ERROR; char *key = NULL; void *handler = NULL; UINT8 pkt_trap = 0; APPL_ENSURE_RET_VAL(adoi && attr, ERR_BAD_PARAM); DAL_ADOI_OPTION_LOOP(adoi) { if (NULL == (key = DAL_ADOI_OPTION_KEY(adoi))) { break; } if (STR_EQUAL(key, DAL_ERPS_K_PKT_TRAP_CPU_OPT)) { if (DAL_ADOI_OPTION_FIELD_MATCH(adoi, DAL_ERPS_F_ENABLE)) { dalAdoiGetOptionUI8(adoi, &pkt_trap); APPL_IF_ERR_DONE(ret, hiErpsTrapCpuSet(pkt_trap)); } } } if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_ERPS_K_PORT_PREFIX))) { // DBG_ALZ("lag port cfg"); DAL_ADOI_ENTRY_LOOP(handler) { char *key = NULL; if (NULL == (key = DAL_ADOI_ENTRY_KEY(handler))) { DBG_ERR("key is NULL"); continue; } /* KEY inner field&value loop */ if (DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_ERPS_K_PORT_ALL)) { _dalErpsPortConfigHandle(adoi, handler, key); } } } if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_ERPS_K_PORT_CFM_PREFIX))) { // DBG_ALZ("lag port cfg"); DAL_ADOI_ENTRY_LOOP(handler) { char *key = NULL; if (NULL == (key = DAL_ADOI_ENTRY_KEY(handler))) { DBG_ERR("key is NULL"); continue; } /* KEY inner field&value loop */ if (DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_ERPS_K_PORT_CFM_ALL)) { _dalErpsPortCfmHandle(adoi, handler, key); } } } done: if (ERR_NO_ERROR != ret) { DE("ERROR: %d", ret); attr->err.errCode = ret; attr->err.errFlag = DAL_ERR_DISP; attr->err.pubEn = TRUE; } return ret; } /* 获取端口硬件转发配置 */ static int _dalErpsPortStateLoad() { int ret = ERR_NO_ERROR; int rv = PFM_ERR_C_OK; dal_ado_t *asdoi = NULL; user_port_list uplist = {}; user_port up = {}; void *handler = NULL; UINT32 instanceNo = 0; int state = 0; if (PFM_ERR_C_OK != uplist_init(&uplist)) { return ERR_NO_MEMORY; } asdoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_ERPS, DAL_CFG_TYPE_ENTRY); dalAdoiEntryTableAppend(asdoi, DAL_ERPS_K_PORT_PREFIX); dalAdoiEntryOperAppend(asdoi, DAL_ERPS_K_PORT_PREFIX, DAL_OPER_GET_ALL); /* 获取端口配置 */ rv = dalGet(asdoi); if(PFM_ERR_C_OK != rv) { //ret = ERR_EXEC; goto done; } if (NULL != (handler = DAL_ADOI_ENTRY(asdoi, DAL_ERPS_K_PORT_PREFIX))) { DAL_ADOI_ENTRY_LOOP(handler) { char *key = NULL; if(DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { /* do nothing */ } if(NULL == (key = DAL_ADOI_ENTRY_KEY(handler))) { DBG_ERR("key is NULL"); continue; } else { DAL_ERPS_KEY_PORT_PARSE(key, up, instanceNo); UP_LIST_CLEAR(&uplist); UP_LIST_ADD(&uplist, up); DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_ERPS_K_PORT_F_STATE)) { dalAdoiGetEntryI32(asdoi, DAL_ERPS_K_PORT_PREFIX, &state); } } /* 进行硬件配置 */ _dalErpsPortStateSet(instanceNo, &uplist, state); } } } done: uplist_free(&uplist); dalAdoiDestroy(asdoi); return ret; } /* 获取端口硬件cfm配置 */ static int _dalErpsPortCfmLoad() { int ret = ERR_NO_ERROR; int rv = PFM_ERR_C_OK; dal_ado_t *asdoi = NULL; void *handler = NULL; asdoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_ERPS, DAL_CFG_TYPE_ENTRY); dalAdoiEntryTableAppend(asdoi, DAL_ERPS_K_PORT_CFM_PREFIX); dalAdoiEntryOperAppend(asdoi, DAL_ERPS_K_PORT_CFM_PREFIX, DAL_OPER_GET_ALL); /* 获取端口配置 */ rv = dalGet(asdoi); if(PFM_ERR_C_OK != rv) { //ret = ERR_EXEC; goto done; } if (NULL != (handler = DAL_ADOI_ENTRY(asdoi, DAL_ERPS_K_PORT_CFM_PREFIX))) { DAL_ADOI_ENTRY_LOOP(handler) { char *key = NULL; if(NULL == (key = DAL_ADOI_ENTRY_KEY(handler))) { DBG_ERR("key is NULL"); continue; } if (DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_ERPS_K_PORT_CFM_ALL)) { _dalErpsPortCfmHandle(asdoi, handler, key); } } } done: dalAdoiDestroy(asdoi); return ret; } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ int dalErpsLoad() { APPL_IF_ERR_RET(dalErpsCfmPortResetAll()); APPL_IF_ERR_RET(_dalErpsPortStateLoad()); APPL_IF_ERR_RET(_dalErpsPortCfmLoad()); return ERR_NO_ERROR; } int dalErpsDefcfgInit() { dalErpsLoad(); return ERR_NO_ERROR; } //此处先由ERPS将mstp所有instance下的状态置为forward,后续mstp适配完之后,此处reset可以直接注释掉 int dalErpsReset() { // return hiMstpReset(); return ERR_NO_ERROR; } void dalErpsTpclReload() { dal_ado_t *asdoi = NULL; dal_attr attr = {}; int ret = ERR_NO_ERROR; /* dal中获取数据 */ asdoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_ERPS, DAL_CFG_TYPE_OPTION); dalAdoiOptionOperAppend(asdoi, DAL_OPER_GET); dalAdoiAddOptionKey(asdoi, DAL_ERPS_K_PKT_TRAP_CPU_OPT); PFM_IF_FAIL_DONE_VOID(dalGet(asdoi)); APPL_IF_ERR_DONE(ret, _dalErpsHandler(asdoi, &attr)); done: dalAdoiDestroy(asdoi); return; } #if 0 //堆叠口生效后需要写硬件将端口转发状态置为forward int dalErpsCascadePortHandle(user_port_list *enableList, user_port_list *disableList) { int ret = ERR_NO_ERROR; int i = 0; for (i = 0; i <= dal_max_erps_inst_cnt; i++) { _dalErpsPortStateSet(i, enableList, STP_FORWARD); } return ret; } #endif //detach 事件无需响应 int dalErpsDetachHandle(char* detachListStr, UINT8 detachFlag) { return ERR_NO_ERROR; } BOOL dalErpsCfmPortInUse(user_port up) { int i = 0; int maxRingNum = 0; maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == UP_PORT(up)) { return TRUE; } } return FALSE; } /* 用于给port分配flowID */ int dalErpsFlowIdAllocByPort(user_port up, int *flowId) { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); int bfdMaxNum = dalBfdMaxSessNum(); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == 0) { dalErpsPortFlowMap[i].port_idx = UP_PORT(up); *flowId = (i + bfdMaxNum); printf("dalErpsFlowIdAllocByPort flowId = %d dalErpsPortFlowMap[%d].port = %d\n", i+bfdMaxNum, i, dalErpsPortFlowMap[i].port_idx); return ERR_NO_ERROR; } } return ERR_NO_MEMORY; } /* 用于重置port下的flowId和packetId */ int dalErpsCfmPortReset(user_port up) { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == UP_PORT(up)) { dalErpsPortFlowMap[i].port_idx = 0; dalErpsPortFlowMap[i].packetId = 0; } } return ERR_NO_ERROR; } /* 用于重置所有flowId和packetId */ int dalErpsCfmPortResetAll() { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); for (i = 0; i < (maxRingNum*2); i++) { dalErpsPortFlowMap[i].port_idx = 0; dalErpsPortFlowMap[i].packetId = 0; } return ERR_NO_ERROR; } /* 用于将port转换成flowID */ int dalErpsPort2FlowId(user_port up, int *flowId) { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); int bfdMaxNum = dalBfdMaxSessNum(); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == UP_PORT(up)) { *flowId = (i + bfdMaxNum); return ERR_NO_ERROR; } } return ERR_NOT_FOUND; } /* 用于将flowID转换成port */ int dalErpsFlowId2Port(int flowId, user_port *up) { int bfdMaxNum = dalBfdMaxSessNum(); int index = 0; index = flowId - bfdMaxNum; DBG("dalErpsFlowId2Port index = %d bfdMaxNum = %d flowId = %d\n", index, bfdMaxNum, flowId); if (dalErpsPortFlowMap[index].port_idx == 0) { DBG("dalErpsFlowId2Port index = %d bfdMaxNum = %d flowId = %d error\n", index, bfdMaxNum, flowId); return ERR_BAD_PARAM; } UP_FROM_IDX(*up, dalErpsPortFlowMap[index].port_idx); return ERR_NO_ERROR; } /* 用于将port转换成packetID */ int dalErpsPort2PacketId(user_port up, UINT32 *packetId) { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == UP_PORT(up)) { *packetId = dalErpsPortFlowMap[i].packetId; return ERR_NO_ERROR; } } return ERR_NOT_FOUND; } /* 用于设置port下的packetId */ int dalErpsPortPacketIdSet(user_port up, UINT32 packetId) { int i = 0; int maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); for (i = 0; i < (maxRingNum*2); i++) { if (dalErpsPortFlowMap[i].port_idx == UP_PORT(up)) { dalErpsPortFlowMap[i].packetId = packetId; return ERR_NO_ERROR; } } return ERR_NOT_FOUND; } int dalErpsLinkChangeCallBack(user_port up, int status) { char key[DAL_KEY_MAX_LEN]={}; dal_ado_t *asdoi=NULL; int ret = 0; DBG("dalErpsLinkChangeCallBack up %d status %d \n", UP_INDEX(up), status); if ((asdoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_ERPS_PORT_LINK, DAL_CFG_TYPE_OPTION)) == NULL) { return ERR_NO_MEMORY; } PFM_IF_FAIL_DONE(ret, dalAdoiOptionOperAppend(asdoi, DAL_OPER_CFG)); snprintf(key, DAL_KEY_MAX_LEN, DAL_ERPS_PORT_LINK_INFO_TBL_IDX, UP_INDEX(up)); PFM_IF_FAIL_DONE(ret, dalAdoiAddOptionKey(asdoi, key)); PFM_IF_FAIL_DONE(ret, dalAdoiAddOptionI32(asdoi, DAL_ERPS_PORT_LINK_FIELD_STATUS, status)); PFM_IF_FAIL_DONE(ret, dalStatChgPub(asdoi, DAL_ERPS_PORT_LINK_INFO_ID)); done: if(asdoi) { dalAdoiDestroy(asdoi); } if(ret != PFM_ERR_C_OK) { return ERR_HW_OP_FAIL; } return ERR_NO_ERROR; } int dalErpsCfmEVCallBack(int flowId) { char key[DAL_KEY_MAX_LEN]={}; user_port up = {}; dal_ado_t *asdoi=NULL; int ret = 0; APPL_IF_ERR_RET(dalErpsFlowId2Port(flowId, &up)); DBG("dalErpsCfmEVCallBack up %d flowId %d \n", UP_INDEX(up), flowId); if ((asdoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_ERPS_PORT_LINK, DAL_CFG_TYPE_OPTION)) == NULL) { return ERR_NO_MEMORY; } PFM_IF_FAIL_DONE(ret, dalAdoiOptionOperAppend(asdoi, DAL_OPER_CFG)); snprintf(key, DAL_KEY_MAX_LEN, DAL_ERPS_PORT_LINK_INFO_TBL_IDX, UP_INDEX(up)); PFM_IF_FAIL_DONE(ret, dalAdoiAddOptionKey(asdoi, key)); PFM_IF_FAIL_DONE(ret, dalAdoiAddOptionI32(asdoi, DAL_ERPS_PORT_LINK_FIELD_STATUS, 0)); PFM_IF_FAIL_DONE(ret, dalStatChgPub(asdoi, DAL_ERPS_PORT_LINK_INFO_ID)); ret = hiErpsOamEntrySet(flowId, FALSE); done: if(asdoi) { dalAdoiDestroy(asdoi); } if(ret != PFM_ERR_C_OK) { return ERR_HW_OP_FAIL; } return ERR_NO_ERROR; } /*! *\fn dalErpsInit *\brief 初始化 *\details * *\param[in] *\param[out] * *\return int *\retval * *\note */ int dalErpsInit(void) { int maxRingNum = 0; maxRingNum = (int)fepCapNumGet(CAP_ERPS_F_MAX_RING, CAP_ERPS_MODE_NAME, FEP_CAP_INVALID_NUM); if (dalErpsPortFlowMap == NULL) { dalErpsPortFlowMap = pal_alloc(sizeof(DAL_ERPS_CFM_INFO)*maxRingNum*2, "dalErpsCfmMap"); } memset(dalErpsPortFlowMap, 0, sizeof(sizeof(DAL_ERPS_CFM_INFO)*maxRingNum*2)); bfdCfmEventHandlerAddCallback(dalErpsCfmEVCallBack); //APPL_IF_ERR_RET_VAL(hiErpsGpioInit(), ERR_INIT); PFM_IF_FAIL_RET_VAL(dalHandlerReg(DAL_MOD_ERPS, _dalErpsHandler), ERR_INIT); return ERR_NO_ERROR; } 参照以上的绑定packetId的方式,我想通过端口和packetIdx绑定分配的packetId应该怎么做,结合我的代码提出建议,添加和修改的内容static int _dalDmpTrafficTestHandler(dal_ado_t *adoi, dal_attr *attr) { void *handler = NULL; char *key = NULL; int upIdx = 0; int packetIdx = 0; user_port up = {}; UINT16 speed = 0; UINT8 enable = 0; UINT32 packetId = 0; char rawPacket[MAX_PAYLOAD_LEN] = {0}; char srcMac[MAC_LEN] ={0}; char dstMac[MAC_LEN] ={0}; char srcIp[IPv4_LEN] = {0}; char dstIp[IPv4_LEN] = {0}; UINT16 lenType = 0; UINT8 vlan = 0; DAL_ADOI_OPTION_LOOP(adoi) { if (NULL == (key = DAL_ADOI_OPTION_KEY(adoi))) { break; } if (STR_EQUAL(key, DAL_TRAFFIC_TEST_GLOBLE)) { if (DAL_ADOI_OPTION_FIELD_MATCH(adoi, DAL_TRAFFIC_TEST_TX_SPEED)) { dalAdoiGetOptionUI16(adoi, &speed); printf("hiTrafficTestSpeedSet[%d]", speed); APPL_IF_ERR_RET(hiTrafficTestSpeedSet(speed)); } else if(DAL_ADOI_OPTION_FIELD_MATCH(adoi, DAL_TRAFFIC_TEST_ENABLE)) { dalAdoiGetOptionUI8(adoi, &enable); printf("hiTrafficTestEnableSet[%d]", enable); if(0 == enable) { APPL_IF_ERR_RET(hiTrafficTestPacketRemove(packetId)); } } } } if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_TRAFFIC_TEST_PORT_TBL))) { DAL_ADOI_ENTRY_LOOP(handler) { if (NULL== (key = DAL_ADOI_ENTRY_KEY(handler)) || !DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_TRAFFIC_TEST_PORT_TBL_ALL)) { continue; } if (DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { printf("key with no fields"); } else { sscanf(key, DAL_TRAFFIC_TEST_PORT_TBL_FMT, &upIdx, &packetIdx); UP_FROM_IDX(up, upIdx); if (UNIT_CURRENT != UP_UNIT(up)) { continue; } DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_RAW_PACKET)) { dalAdoiGetEntryStr(adoi, DAL_TRAFFIC_TEST_PORT_TBL, rawPacket, MAX_PAYLOAD_LEN); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_SRC_MAC)) { dalAdoiGetEntryStr(adoi, DAL_TRAFFIC_TEST_PORT_TBL, srcMac, MAC_LEN); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_DST_MAC)) { dalAdoiGetEntryStr(adoi, DAL_TRAFFIC_TEST_PORT_TBL, dstMac, MAC_LEN); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_SRC_IP)) { dalAdoiGetEntryStr(adoi, DAL_TRAFFIC_TEST_PORT_TBL, srcIp, IPv4_LEN); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_DST_IP)) { dalAdoiGetEntryStr(adoi, DAL_TRAFFIC_TEST_PORT_TBL, dstIp, IPv4_LEN); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_LENTYPE)) { dalAdoiGetEntryUI16(adoi, DAL_TRAFFIC_TEST_PORT_TBL, &lenType); } else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_VLAN)) { dalAdoiGetEntryUI8(adoi, DAL_TRAFFIC_TEST_PORT_TBL, &vlan); } else { printf("Invalid field %s !", DAL_ADOI_ENTRY_FIELD(handler)); } } } } printf("Calling hiTrafficTestPacketSet with:\n"); printf(" rawPacket: %s\n", rawPacket); printf(" srcMac: %s\n", srcMac); printf(" dstMac: %s\n", dstMac); printf(" srcIp: %s\n", srcIp); printf(" dstIp: %s\n", dstIp); printf(" lenType: %d\n", lenType); printf(" vlan: %d\n", vlan); APPL_IF_ERR_RET(hiTrafficTestPacketSet(up, rawPacket, srcMac, dstMac, srcIp, dstIp, lenType, vlan, &packetId)); } return ERR_NO_ERROR; }
10-31
<think>我们参考之前ERPS代码中绑定packetId的方式,它通过一个全局数组`dalErpsPortFlowMap`来维护端口与packetId/flowId的映射关系。在我们的流量测试场景中,需要将端口(up)和包索引(packetIdx)组合起来作为唯一键来绑定packetId。 建议修改步骤: 1. 定义一个结构体来存储每个端口和包索引对应的packetId。 2. 创建一个全局数组(或哈希表)来维护映射关系。 3. 在设置报文时(调用`hiTrafficTestPacketSet`后),将分配的packetId存储到该全局结构中,以便后续通过端口和包索引来查找。 4. 在需要移除报文时,通过端口和包索引找到对应的packetId,然后调用移除函数。 具体修改如下: 第一步:定义映射结构体 在文件合适位置(例如,在全局变量定义处)添加如下结构体和数组: ```c typedef struct { int port_idx; // 端口索引 int packet_idx; // 包索引 UINT32 packetId; // 分配的packetId } DAL_TRAFFIC_PACKET_MAP; static DAL_TRAFFIC_PACKET_MAP *dalTrafficPacketMap = NULL; static int dalTrafficMaxPackets = 0; // 最大记录数,根据需求初始化 ``` 第二步:初始化映射数组 在初始化函数中(例如`dalDmpTrafficTestInit`)分配数组内存。如果没有初始化函数,可以在第一次使用时动态分配。假设我们支持每个端口最多有N个包索引(例如每个端口最多10个不同的测试包),那么最大记录数为端口数*N。但为了简化,我们可以根据实际需要设置一个最大值。 第三步:在报文设置函数中存储映射关系 在`_dalDmpTrafficTestHandler`函数中,调用`hiTrafficTestPacketSet`成功后,将返回的`packetId`与当前的`upIdx`和`packetIdx`一起存储到映射数组中。 第四步:在需要移除报文时,通过端口索引和包索引查找packetId,然后调用移除函数。 另外,我们注意到在全局选项`DAL_TRAFFIC_TEST_ENABLE`中,我们尝试移除报文,但此时`packetId`变量未正确设置(它只是局部变量且未初始化)。因此,我们需要根据enable状态来执行不同的操作:当enable为0时,我们需要移除该端口和包索引对应的报文。 但是,在当前的代码结构中,全局选项的enable是用来控制整个流量测试的开关,而每个端口的报文配置是在后面的循环中处理的。因此,我们需要调整逻辑: 建议: 1. 将全局使能开关的处理放在最后,这样我们可以先配置好所有端口的报文,然后再开启测试(或者关闭测试)。 2. 或者,在全局使能关闭时,我们需要遍历所有已配置的报文并移除它们。 然而,根据代码,全局使能开关和端口配置是两个独立的配置项,因此可能需要分别处理。 考虑到当前代码结构,我们可以在全局使能关闭时,移除所有已经分配的报文。为此,我们需要维护一个全局的映射表,记录所有分配的packetId(按端口和包索引)。 但需要注意的是,在同一个配置请求中,可能同时包含全局使能关闭和端口配置的删除,因此我们需要先处理端口配置,再处理全局使能。 具体修改如下: 1. 定义映射数组和相关函数(查找、添加、删除)。 2. 在`dalDmpTrafficTestInit`中初始化映射数组(假设最大支持100个映射)。 3. 在报文设置成功后将映射添加到数组。 4. 当全局使能关闭时,遍历映射数组,移除所有报文并重置数组。 5. 同时,我们也可以支持针对特定端口和包索引的删除操作(通过配置相应的字段,例如删除某个端口的某个报文)。 由于当前代码中,端口配置循环内没有处理删除操作(只有设置),因此我们需要在配置中增加一个操作类型(例如,通过操作符区分是添加还是删除)。但是,从当前配置框架看,似乎是通过全局使能来控制总开关,而端口配置是独立的。 考虑到时间,我们先修改为:当全局使能关闭时,移除所有报文。同时,在端口配置循环中,每次都是设置报文(如果之前设置过,则先移除再设置?)但是,硬件层接口`hiTrafficTestPacketSet`可能并不支持更新,所以每次设置新的报文之前,如果该端口和包索引已经存在,则先移除旧的。 因此,我们在设置报文前,先查找该端口和包索引是否已经存在packetId,如果存在,则先移除。 修改代码详细步骤: 步骤1:定义映射结构体和全局数组 ```c typedef struct { int port_idx; int packet_idx; UINT32 packetId; } TRAFFIC_PACKET_MAP; #define MAX_TRAFFIC_PACKET_MAP 100 // 最大映射数量 static TRAFFIC_PACKET_MAP g_trafficPacketMap[MAX_TRAFFIC_PACKET_MAP] = {0}; ``` 步骤2:在报文设置前,查找是否已存在相同端口和包索引的映射,如果存在则先移除 ```c // 查找映射 static UINT32 _dalTrafficPacketMapFind(int port_idx, int packet_idx) { int i; for (i = 0; i < MAX_TRAFFIC_PACKET_MAP; i++) { if (g_trafficPacketMap[i].port_idx == port_idx && g_trafficPacketMap[i].packet_idx == packet_idx) { return g_trafficPacketMap[i].packetId; } } return 0; // 0表示未找到,因为packetId通常不为0 } // 移除映射 static void _dalTrafficPacketMapRemove(int port_idx, int packet_idx) { int i; for (i = 0; i < MAX_TRAFFIC_PACKET_MAP; i++) { if (g_trafficPacketMap[i].port_idx == port_idx && g_trafficPacketMap[i].packet_idx == packet_idx) { g_trafficPacketMap[i].port_idx = 0; g_trafficPacketMap[i].packet_idx = 0; g_trafficPacketMap[i].packetId = 0; break; } } } // 添加映射 static int _dalTrafficPacketMapAdd(int port_idx, int packet_idx, UINT32 packetId) { int i; // 先检查是否已经存在,如果存在则更新 for (i = 0; i < MAX_TRAFFIC_PACKET_MAP; i++) { if (g_trafficPacketMap[i].port_idx == port_idx && g_trafficPacketMap[i].packet_idx == packet_idx) { g_trafficPacketMap[i].packetId = packetId; return ERR_NO_ERROR; } } // 不存在,则找一个空位 for (i = 0; i < MAX_TRAFFIC_PACKET_MAP; i++) { if (g_trafficPacketMap[i].port_idx == 0 && g_trafficPacketMap[i].packet_idx == 0) { g_trafficPacketMap[i].port_idx = port_idx; g_trafficPacketMap[i].packet_idx = packet_idx; g_trafficPacketMap[i].packetId = packetId; return ERR_NO_ERROR; } } return ERR_NO_MEMORY; } ``` 步骤3:在`_dalDmpTrafficTestHandler`函数中,处理端口配置时,先尝试移除旧的报文(如果存在),然后再设置新的报文,并记录新的packetId。 在端口配置循环内,调用`hiTrafficTestPacketSet`之前,添加: ```c // 检查该端口和包索引是否已经存在一个报文,如果存在则先移除 UINT32 oldPacketId = _dalTrafficPacketMapFind(upIdx, packetIdx); if (oldPacketId != 0) { APPL_IF_ERR_RET(hiTrafficTestPacketRemove(oldPacketId)); _dalTrafficPacketMapRemove(upIdx, packetIdx); } ``` 然后,调用`hiTrafficTestPacketSet`成功后,添加新的映射: ```c // 设置新的报文 APPL_IF_ERR_RET(hiTrafficTestPacketSet(up, rawPacket, srcMac, dstMac, srcIp, dstIp, lenType, vlan, &packetId)); // 存储映射 APPL_IF_ERR_RET(_dalTrafficPacketMapAdd(upIdx, packetIdx, packetId)); ``` 步骤4:在全局使能关闭时(即enable=0),移除所有已配置的报文,并清空映射数组。 ```c if(DAL_ADOI_OPTION_FIELD_MATCH(adoi, DAL_TRAFFIC_TEST_ENABLE)) { dalAdoiGetOptionUI8(adoi, &enable); printf("hiTrafficTestEnableSet[%d]", enable); if(0 == enable) { // 移除所有报文 int i; for (i = 0; i < MAX_TRAFFIC_PACKET_MAP; i++) { if (g_trafficPacketMap[i].packetId != 0) { hiTrafficTestPacketRemove(g_trafficPacketMap[i].packetId); g_trafficPacketMap[i].packetId = 0; g_trafficPacketMap[i].port_idx = 0; g_trafficPacketMap[i].packet_idx = 0; } } } } ``` 注意:由于全局使能关闭的处理在端口配置循环之前,我们需要将全局使能关闭的处理移到端口配置循环之后?或者确保全局使能关闭时,端口配置循环不再执行?目前代码中,全局选项和端口配置是独立的,都会执行。但在实际使用中,可能同时下发关闭和端口配置。因此,我们调整顺序:先处理端口配置(这样如果有新的配置,会先设置),然后处理全局使能关闭(关闭时会移除所有报文,包括刚刚设置的)。这显然不是我们想要的。 因此,我们需要调整逻辑:全局使能关闭应该只影响之前配置的报文,而不影响本次配置的报文。或者,我们认为全局使能关闭是独立操作,它关闭整个流量测试,然后端口配置是独立的,即使配置了报文,如果没有开启全局使能,也不会发送。但是,硬件层可能是在设置报文时就开始发送(取决于硬件设计)。所以,这个设计需要明确。 为了避免冲突,我们修改:全局使能开启/关闭只控制总开关,而报文的设置和删除通过端口配置来独立控制。因此,全局使能关闭时,我们不应该移除报文,而应该停止发送(可能硬件层有使能开关)。但是,从函数名`hiTrafficTestEnableSet`看,它可能是控制总开关。而报文的移除应该由单独的配置操作触发。 根据当前代码,报文的移除操作还没有在端口配置中实现。我们可以在端口配置中增加一个字段(例如enable),当该字段为0时,移除该端口和包索引对应的报文。 因此,我们修改方案: 1. 不在全局使能关闭时移除报文,而是停止发送(调用`hiTrafficTestEnableSet(0)`)。 2. 在端口配置循环中,允许通过一个字段(比如`oper`)来指定操作(添加或删除报文)。 但是,由于时间,我们暂且按照之前的思路:全局使能关闭时移除所有报文。并且,将全局使能关闭的处理移到函数的最后,这样在关闭之前,我们可以先处理端口配置(可能是删除某些报文,也可能是添加)。然后,当全局使能关闭时,我们移除所有报文(包括本次配置的报文)。 这样做的效果是:当配置一个关闭命令时,会清除之前所有的报文配置。 因此,调整代码顺序:将全局选项循环移到端口配置循环的后面。 修改代码结构: ```c // 先处理端口配置部分 if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_TRAFFIC_TEST_PORT_TBL))) { // 原来的循环 } // 再处理全局选项 DAL_ADOI_OPTION_LOOP(adoi) { // 原来的选项处理,特别注意全局使能关闭的处理会移除所有报文 } ``` 这样,在全局使能关闭之前,本次配置的报文已经设置并添加到映射数组,然后关闭使能时会被移除。但是,如果本次配置的报文希望保留(在下次使能开启时使用),那么就不应该在关闭时移除。所以这取决于需求。 考虑到这个流量测试功能,当全局使能关闭时,应该停止发送并清除所有测试报文。所以移除所有报文是合理的。 因此,我们调整顺序,并按照上述步骤修改代码。 总结修改点: 1. 定义映射数组和操作函数。 2. 在设置报文前,若已存在则先移除旧报文。 3. 设置成功后添加映射。 4. 处理全局使能关闭时,移除所有报文并清除映射。 5. 调整代码顺序,先处理端口配置,再处理全局选项。 注意:需要将全局使能关闭的处理代码移到端口配置循环之后。 修改后的`_dalDmpTrafficTestHandler`函数框架如下: ```c static int _dalDmpTrafficTestHandler(dal_ado_t *adoi, dal_attr *attr) { // ... 变量定义 ... // 第一步:处理端口配置表 if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_TRAFFIC_TEST_PORT_TBL))) { // 循环处理每个端口配置 // 在设置报文前,检查并移除旧的,然后设置新的并添加到映射 } // 第二步:处理全局选项 DAL_ADOI_OPTION_LOOP(adoi) { // 如果遇到全局使能关闭,则移除所有报文并重置映射数组 // 注意:这里使能关闭处理会移除包括上面刚设置的报文 } return ERR_NO_ERROR; } ``` 由于代码较长,下面只展示修改后的关键部分。 最后,需要在文件开头定义映射数组和最大数量: ```c #define MAX_TRAFFIC_PACKET_MAP 100 typedef struct { int port_idx; int packet_idx; UINT32 packetId; } TRAFFIC_PACKET_MAP; static TRAFFIC_PACKET_MAP g_trafficPacketMap[MAX_TRAFFIC_PACKET_MAP] = {0}; ``` 并实现上述三个辅助函数(`_dalTrafficPacketMapFind`, `_dalTrafficPacketMapRemove`, `_dalTrafficPacketMapAdd`)。 注意:这个映射数组不是线程安全的,如果多线程调用需要加锁。这里假设在DAL层是单线程处理的。 以上修改即可实现通过端口和包索引绑定packetId。 </think>### 绑定端口与PacketIdx的方案设计 根据您的代码结构和需求,建议采用以下方案实现端口与PacketIdx绑定分配的PacketId: #### 1. 定义全局映射结构体(在文件顶部添加) ```c typedef struct { int port_idx; // 端口索引 int packet_idx; // 报文索引 UINT32 packetId; // 分配的packetId } DAL_TRAFFIC_PACKET_MAP; static DAL_TRAFFIC_PACKET_MAP *dalTrafficPacketMap = NULL; static int dalTrafficMaxPackets = 0; // 最大映射数量 ``` #### 2. 初始化映射数组(在初始化函数中添加) ```c int dalDmpTrafficTestInit(void) { // 假设最大支持1000个映射关系 dalTrafficMaxPackets = 1000; dalTrafficPacketMap = pal_alloc(sizeof(DAL_TRAFFIC_PACKET_MAP) * dalTrafficMaxPackets, "trafficMap"); if (!dalTrafficPacketMap) return ERR_NO_MEMORY; memset(dalTrafficPacketMap, 0, sizeof(DAL_TRAFFIC_PACKET_MAP) * dalTrafficMaxPackets); return ERR_NO_ERROR; } ``` #### 3. 修改报文设置函数(在`hiTrafficTestPacketSet`后添加映射) ```c // 在APPL_IF_ERR_RET(hiTrafficTestPacketSet(...));之后添加: // 存储映射关系 int mapIndex = -1; for (int i = 0; i < dalTrafficMaxPackets; i++) { if (dalTrafficPacketMap[i].port_idx == 0) { mapIndex = i; break; } } if (mapIndex >= 0) { dalTrafficPacketMap[mapIndex].port_idx = upIdx; dalTrafficPacketMap[mapIndex].packet_idx = packetIdx; dalTrafficPacketMap[mapIndex].packetId = packetId; printf("Mapped: PortIdx=%d, PktIdx=%d -> PacketId=0x%X\n", upIdx, packetIdx, packetId); } else { printf("ERROR: Traffic packet map full!\n"); } ``` #### 4. 添加通过端口和PacketIdx查找PacketId的函数 ```c UINT32 dalTrafficGetPacketId(int port_idx, int packet_idx) { for (int i = 0; i < dalTrafficMaxPackets; i++) { if (dalTrafficPacketMap[i].port_idx == port_idx && dalTrafficPacketMap[i].packet_idx == packet_idx) { return dalTrafficPacketMap[i].packetId; } } return 0; // 未找到返回0 } ``` #### 5. 修改全局使能关闭逻辑(使用映射关系) ```c // 修改全局ENABLE处理部分 else if(DAL_ADOI_OPTION_FIELD_MATCH(adoi, DAL_TRAFFIC_TEST_ENABLE)) { dalAdoiGetOptionUI8(adoi, &enable); printf("hiTrafficTestEnableSet[%d]", enable); if(0 == enable) { // 移除所有已映射的报文 for (int i = 0; i < dalTrafficMaxPackets; i++) { if (dalTrafficPacketMap[i].port_idx != 0) { APPL_IF_ERR_RET(hiTrafficTestPacketRemove(dalTrafficPacketMap[i].packetId)); printf("Removed PacketId=0x%X (PortIdx=%d, PktIdx=%d)\n", dalTrafficPacketMap[i].packetId, dalTrafficPacketMap[i].port_idx, dalTrafficPacketMap[i].packet_idx); // 清除映射 memset(&dalTrafficPacketMap[i], 0, sizeof(DAL_TRAFFIC_PACKET_MAP)); } } } } ``` #### 6. 添加特定报文移除支持(在端口配置循环内) ```c // 在字段循环中添加删除操作支持 else if(DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_TRAFFIC_TEST_PORT_REMOVE)) { UINT8 removeFlag = 0; dalAdoiGetEntryUI8(adoi, DAL_TRAFFIC_TEST_PORT_TBL, &removeFlag); if (removeFlag) { UINT32 pid = dalTrafficGetPacketId(upIdx, packetIdx); if (pid) { APPL_IF_ERR_RET(hiTrafficTestPacketRemove(pid)); printf("Removed specific packet: PortIdx=%d, PktIdx=%d (ID=0x%X)\n", upIdx, packetIdx, pid); // 清除映射 for (int i = 0; i < dalTrafficMaxPackets; i++) { if (dalTrafficPacketMap[i].port_idx == upIdx && dalTrafficPacketMap[i].packet_idx == packetIdx) { memset(&dalTrafficPacketMap[i], 0, sizeof(DAL_TRAFFIC_PACKET_MAP)); break; } } } else { printf("WARN: Packet not found for removal: PortIdx=%d, PktIdx=%d\n", upIdx, packetIdx); } } } ``` #### 7. 内存释放(在模块卸载函数中添加) ```c void dalDmpTrafficTestCleanup() { if (dalTrafficPacketMap) { pal_free(dalTrafficPacketMap); dalTrafficPacketMap = NULL; } } ``` ### 关键改进说明 1. **双重索引映射**: - 使用`(port_idx, packet_idx)`组合作为唯一键 - 支持同一端口的不同测试报文管理 - 类似ERPS中的`dalErpsPortFlowMap`设计 2. **生命周期管理**: - 初始化时分配固定大小的映射数组 - 报文设置时自动创建映射 - 移除时自动清理映射条目 - 模块卸载时释放内存 3. **灵活的删除操作**: - 支持全局关闭时清除所有报文 - 支持基于端口和PacketIdx的精准删除 - 删除时自动维护映射关系 4. **错误处理增强**: - 映射满时提示错误 - 删除不存在的报文时给出警告 - 每个操作都有详细日志输出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值