CSE-release/fmapi_mcc_handler.c
2024-04-08 06:22:45 +00:00

1097 lines
30 KiB
C

/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file fmapi_mcc_handler.c
*
* @brief Code file for methods to respond to FM API commands
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Jan 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
/* gettid()
*/
#define _GNU_SOURCE
#include <unistd.h>
/* printf()
*/
#include <stdio.h>
/* memset()
*/
#include <string.h>
/* struct timespec
* timespec_get()
*
*/
#include <time.h>
/* autl_prnt_buf()
*/
#include <arrayutils.h>
/* mctp_init()
* mctp_set_mh()
* mctp_run()
*/
#include <mctp.h>
#include <ptrqueue.h>
#include <timeutils.h>
#include <cxlstate.h>
#include "signals.h"
#include "options.h"
#include "state.h"
#include <fmapi.h>
#include "fmapi_handler.h"
/* MACROS ====================================================================*/
#ifdef CSE_VERBOSE
#define INIT unsigned step = 0;
#define ENTER if (opts[CLOP_VERBOSITY].u64 & CLVB_CALLSTACK) printf("%d:%s Enter\n", gettid(), __FUNCTION__);
#define STEP step++; if (opts[CLOP_VERBOSITY].u64 & CLVB_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step);
#define HEX32(m, i) if (opts[CLOP_VERBOSITY].u64 & CLVB_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, m, i);
#define INT32(m, i) if (opts[CLOP_VERBOSITY].u64 & CLVB_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, m, i);
#define EXIT(rc) if (opts[CLOP_VERBOSITY].u64 & CLVB_CALLSTACK) printf("%d:%s Exit: %d\n", gettid(), __FUNCTION__,rc);
#else
#define ENTER
#define EXIT(rc)
#define STEP
#define HEX32(m, i)
#define INT32(m, i)
#define INIT
#endif // CSE_VERBOSE
#define IFV(u) if (opts[CLOP_VERBOSITY].u64 & u)
#define ISO_TIME_BUF_LEN 32
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
/* GLOBAL VARIABLES ==========================================================*/
/* FUNCTIONS =================================================================*/
/**
* Handler for FM API MCC Get LD Alloc Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_get_ld_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
unsigned i, end;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get LD Allocations. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
// If start num exceeds number of vppbids return invalid
if (req->obj.mcc_alloc_get_req.start > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested start ldid exceeds number of logical devices on this mld. Start: %d Actual: %d\n", now, req->obj.mcc_alloc_get_req.start, p->mld->num);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_alloc_get_rsp.total = p->mld->num;
rsp->obj.mcc_alloc_get_rsp.granularity = p->mld->granularity;
rsp->obj.mcc_alloc_get_rsp.start = req->obj.mcc_alloc_get_req.start;
rsp->obj.mcc_alloc_get_rsp.num = 0;
end = p->mld->num;
if (req->obj.mcc_alloc_get_req.limit < (end - req->obj.mcc_alloc_get_req.start) )
end = req->obj.mcc_alloc_get_req.start + req->obj.mcc_alloc_get_req.limit;
for ( i = req->obj.mcc_alloc_get_req.start ; i < end ; i++ )
{
rsp->obj.mcc_alloc_get_rsp.list[rsp->obj.mcc_alloc_get_rsp.num].rng1 = p->mld->rng1[i];
rsp->obj.mcc_alloc_get_rsp.list[rsp->obj.mcc_alloc_get_rsp.num].rng2 = p->mld->rng2[i];
rsp->obj.mcc_alloc_get_rsp.num++;
}
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Get QoS Allocated BW Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_get_qos_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
unsigned i;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get QoS Allocated. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_qos_bw_alloc.num = req->obj.mcc_qos_bw_alloc_get_req.num;
rsp->obj.mcc_qos_bw_alloc.start = req->obj.mcc_qos_bw_alloc_get_req.start;
if ( (p->mld->num - req->obj.mcc_qos_bw_alloc_get_req.start) < req->obj.mcc_qos_bw_alloc_get_req.num )
rsp->obj.mcc_qos_bw_alloc.num = p->mld->num - req->obj.mcc_qos_bw_alloc_get_req.start;
for ( i = 0 ; i < rsp->obj.mcc_qos_bw_alloc.num ; i++)
rsp->obj.mcc_qos_bw_alloc.list[i] = p->mld->alloc_bw[i+req->obj.mcc_qos_bw_alloc_get_req.start];
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Get QoS Control Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_get_qos_ctrl(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get QoS Control. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_qos_ctrl.epc_en = p->mld->epc_en;
rsp->obj.mcc_qos_ctrl.ttr_en = p->mld->ttr_en;
rsp->obj.mcc_qos_ctrl.egress_mod_pcnt = p->mld->egress_mod_pcnt;
rsp->obj.mcc_qos_ctrl.egress_sev_pcnt = p->mld->egress_sev_pcnt;
rsp->obj.mcc_qos_ctrl.sample_interval = p->mld->sample_interval;
rsp->obj.mcc_qos_ctrl.rcb = p->mld->rcb;
rsp->obj.mcc_qos_ctrl.comp_interval = p->mld->comp_interval;
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Get QoS BW Limit Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_get_qos_limit(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
int i;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get QoS Limit. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_qos_bw_limit.num = req->obj.mcc_qos_bw_limit_get_req.num;
rsp->obj.mcc_qos_bw_limit.start = req->obj.mcc_qos_bw_limit_get_req.start;
if ( (p->mld->num - req->obj.mcc_qos_bw_limit_get_req.start) < req->obj.mcc_qos_bw_limit_get_req.num )
rsp->obj.mcc_qos_bw_limit.num = p->mld->num - req->obj.mcc_qos_bw_limit_get_req.start;
for ( i = 0 ; i < rsp->obj.mcc_qos_bw_limit.num ; i++ )
rsp->obj.mcc_qos_bw_limit.list[i] = p->mld->bw_limit[i+req->obj.mcc_qos_bw_limit_get_req.start];
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Get QoS Status Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_get_qos_stat(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get QoS Status. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_qos_stat_rsp.bp_avg_pcnt = p->mld->bp_avg_pcnt;
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Info Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_info(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Get LD Info. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
STEP // 7: Prepare Response Object
rsp->obj.mcc_info_rsp.size = p->mld->memory_size ;
rsp->obj.mcc_info_rsp.num = p->mld->num;
rsp->obj.mcc_info_rsp.epc = p->mld->epc;
rsp->obj.mcc_info_rsp.ttr = p->mld->ttr;
STEP // 8: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 9: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Set LD Alloc Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Set return code
* 8: Prepare Response Object
* 9: Serialize Response Object
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_set_ld_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
int i;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Set LD Allocations. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
// Verify requested LD count does not exceed actual LD count
if (req->obj.mcc_alloc_set_req.num > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested number of LD entries exceeds number of LDs present. Requested: %d Present: %d\n", now, req->obj.mcc_alloc_set_req.num, p->mld->num);
goto send;
}
// Verify the start LD ID does not exceed actual LD count
if (req->obj.mcc_alloc_set_req.start > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested started LD ID exceeds number of LDs present. Start: %d Present: %d\n", now, req->obj.mcc_alloc_set_req.start, p->mld->num);
goto send;
}
// Verify the final LD ID does not exceed actual LD count
if ((req->obj.mcc_alloc_set_req.start + req->obj.mcc_alloc_set_req.num) > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested start + num exceeds number of LDs present. End: %d Present: %d\n", now, req->obj.mcc_alloc_set_req.start+req->obj.mcc_alloc_set_req.num, p->mld->num);
goto send;
}
STEP // 6: Perform Action
IFV(CLVB_ACTIONS) printf("%s ACT: Setting LD Allocations on PPID: %d\n", now, p->ppid);
for ( i = 0 ; i < req->obj.mcc_alloc_set_req.num ; i++ )
{
p->mld->rng1[i+req->obj.mcc_alloc_set_req.start] = req->obj.mcc_alloc_set_req.list[i].rng1;
p->mld->rng2[i+req->obj.mcc_alloc_set_req.start] = req->obj.mcc_alloc_set_req.list[i].rng2;
}
STEP // 7: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 8: Prepare Response Object
rsp->obj.mcc_alloc_set_rsp.num = req->obj.mcc_alloc_set_req.num;
rsp->obj.mcc_alloc_set_rsp.start = req->obj.mcc_alloc_set_req.start;
for ( i = 0 ; i < rsp->obj.mcc_alloc_set_rsp.num ; i++ ) {
rsp->obj.mcc_alloc_set_rsp.list[i].rng1 = p->mld->rng1[i+rsp->obj.mcc_alloc_set_rsp.start];
rsp->obj.mcc_alloc_set_rsp.list[i].rng2 = p->mld->rng2[i+rsp->obj.mcc_alloc_set_rsp.start];
}
STEP // 9: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Set QoS BW Allocated Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Set return code
* 8: Prepare Response Object
* 9: Serialize Response Object
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_set_qos_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
int i;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Set QoS Allocated. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
// Verify requested LD count does not exceed actual LD count
if (req->obj.mcc_qos_bw_alloc.num > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested number of LD entries exceeds number of LDs present. Requested: %d Present: %d\n", now, req->obj.mcc_qos_bw_alloc.num, p->mld->num);
goto send;
}
// Verify requested LD count does not exceed actual LD count
if ((req->obj.mcc_qos_bw_alloc.start + req->obj.mcc_qos_bw_alloc.num) > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested start + number of LD entries exceeds number of LDs present. Requested: %d Present: %d\n", now, req->obj.mcc_qos_bw_alloc.num, p->mld->num);
goto send;
}
STEP // 6: Perform Action
IFV(CLVB_ACTIONS) printf("%s ACT: Setting QoS Allocations on PPID: %d\n", now, p->ppid);
for ( i = 0 ; i < req->obj.mcc_qos_bw_alloc.num ; i++ )
p->mld->alloc_bw[i+req->obj.mcc_qos_bw_alloc.start] = req->obj.mcc_qos_bw_alloc.list[i];
STEP // 7: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 8: Prepare Response Object
rsp->obj.mcc_qos_bw_alloc.start = req->obj.mcc_qos_bw_alloc.start;
rsp->obj.mcc_qos_bw_alloc.num = req->obj.mcc_qos_bw_alloc.num;
for ( i = 0 ; i < rsp->obj.mcc_qos_bw_alloc.num ; i++ )
rsp->obj.mcc_qos_bw_alloc.list[i] = p->mld->alloc_bw[i+rsp->obj.mcc_qos_bw_alloc.start];
STEP // 9: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Set QoS Control Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Set return code
* 8: Prepare Response Object
* 9: Serialize Response Object
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_set_qos_ctrl(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Set QoS Control. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
STEP // 6: Perform Action
IFV(CLVB_ACTIONS) printf("%s ACT: Setting QoS Control on PPID: %d\n", now, p->ppid);
p->mld->epc_en = req->obj.mcc_qos_ctrl.epc_en;
p->mld->ttr_en = req->obj.mcc_qos_ctrl.ttr_en;
p->mld->egress_mod_pcnt = req->obj.mcc_qos_ctrl.egress_mod_pcnt;
p->mld->egress_sev_pcnt = req->obj.mcc_qos_ctrl.egress_sev_pcnt;
p->mld->sample_interval = req->obj.mcc_qos_ctrl.sample_interval;
p->mld->rcb = req->obj.mcc_qos_ctrl.rcb;
p->mld->comp_interval = req->obj.mcc_qos_ctrl.comp_interval;
STEP // 7: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 8: Prepare Response Object
rsp->obj.mcc_qos_ctrl.epc_en = p->mld->epc_en;
rsp->obj.mcc_qos_ctrl.ttr_en = p->mld->ttr_en;
rsp->obj.mcc_qos_ctrl.egress_mod_pcnt = p->mld->egress_mod_pcnt;
rsp->obj.mcc_qos_ctrl.egress_sev_pcnt = p->mld->egress_sev_pcnt;
rsp->obj.mcc_qos_ctrl.sample_interval = p->mld->sample_interval;
rsp->obj.mcc_qos_ctrl.rcb = p->mld->rcb;
rsp->obj.mcc_qos_ctrl.comp_interval = p->mld->comp_interval;
STEP // 9: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}
/**
* Handler for FM API MCC Set QoS BW Limit Opcode
*
* @param m struct mctp*
* @param mm struct mctp_msg*
* @param req struct fmapi_msg*
* @param rsp struct fmapi_msg*
* @return length of serialized message (FMLN_HDR + object)
*
* STEPS
* 1: Initialize variables
* 2: Deserialize Request Header
* 3: Deserialize Request Object
* 4: Extract parameters
* 5: Validate Inputs
* 6: Perform Action
* 7: Prepare Response Object
* 8: Serialize Response Object
* 9: Set return code
* 10: Fill Response Header
* 11: Serialize Response Header
* 12: Return length of MF API Message (FMLN_HDR + object)
*/
int fmop_mcc_set_qos_limit(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp)
{
INIT
char now[ISO_TIME_BUF_LEN];
unsigned rc;
int rv, len;
int i;
ENTER
STEP // 1: Initialize variables
rv = 0;
len = 0;
rc = FMRC_INVALID_INPUT;
isotime(now, ISO_TIME_BUF_LEN);
STEP // 2: Deserialize Header
if ( fmapi_deserialize(&req->hdr, req->buf->hdr, FMOB_HDR, 0) <= 0)
goto end;
STEP // 3: Deserialize Request Object
if ( fmapi_deserialize(&req->obj, req->buf->payload, fmapi_fmob_req(req->hdr.opcode), NULL) < 0 )
goto end;
STEP // 4: Extract parameters
IFV(CLVB_COMMANDS) printf("%s CMD: FM API MCC Set QoS Limit. PPID: %d\n", now, p->ppid);
STEP // 5: Validate Inputs
// If port does not have an mld device return invalid
if (p->mld == NULL)
{
IFV(CLVB_ERRORS) printf("%s ERR: Port not connected to an MLD\n", now);
goto send;
}
// Verify requested LD count does not exceed actual LD count
if (req->obj.mcc_qos_bw_limit.num > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested number of LD entries exceeds number of LDs present. Requested: %d Present: %d\n", now, req->obj.mcc_qos_bw_limit.num, p->mld->num);
goto send;
}
// Verify requested LD count does not exceed actual LD count
if ((req->obj.mcc_qos_bw_limit.start + req->obj.mcc_qos_bw_limit.num) > p->mld->num)
{
IFV(CLVB_ERRORS) printf("%s ERR: Requested start + number of LD entries exceeds number of LDs present. Requested: %d Present: %d\n", now, req->obj.mcc_qos_bw_limit.num, p->mld->num);
goto send;
}
STEP // 6: Perform Action
IFV(CLVB_ACTIONS) printf("%s ACT: Setting QoS Limit on PPID: %d\n", now, p->ppid);
for ( i = 0 ; i < req->obj.mcc_qos_bw_limit.num ; i++ )
p->mld->bw_limit[i+req->obj.mcc_qos_bw_limit.start] = req->obj.mcc_qos_bw_limit.list[i];
STEP // 7: Set return code
rc = FMRC_SUCCESS;
send:
STEP // 8: Prepare Response Object
rsp->obj.mcc_qos_bw_limit.start = req->obj.mcc_qos_bw_limit.start;
rsp->obj.mcc_qos_bw_limit.num = req->obj.mcc_qos_bw_limit.num;
for ( i = 0 ; i < rsp->obj.mcc_qos_bw_limit.num ; i++ )
rsp->obj.mcc_qos_bw_limit.list[i] = p->mld->bw_limit[i+req->obj.mcc_qos_bw_limit.start];
STEP // 9: Serialize Response Object
len = fmapi_serialize(rsp->buf->payload, &rsp->obj, fmapi_fmob_rsp(req->hdr.opcode));
STEP // 10: Fill Response Header
rv = fmapi_fill_hdr(&rsp->hdr, FMMT_RESP, req->hdr.tag, req->hdr.opcode, 0, len, rc, 0);
STEP // 11: Serialize Response Header
fmapi_serialize(rsp->buf->hdr, &rsp->hdr, FMOB_HDR);
end:
EXIT(rc)
STEP // 12: Return length of MF API Message (FMLN_HDR + object)
return rv;
}