Release candidate

This commit is contained in:
Grant Mackey 2024-04-02 04:59:26 +00:00
parent 1d44142f42
commit b693730c7d
15 changed files with 10806 additions and 0 deletions

2659
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

62
Makefile Normal file
View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: Apache-2.0
# ******************************************************************************
#
# @file Makefile
#
# @brief Makefile for Jack CXL Fabric Management CLI Tool
#
# @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
#
# @date Mar 2024
# @author Barrett Edwards <code@jrlabs.io>
#
# ******************************************************************************
CC=gcc
CFLAGS= -g3 -O0 -Wall -Wextra
MACROS=-D JACK_VERBOSE
INCLUDE_DIR=/usr/local/include
LIB_DIR=/usr/local/lib
INCLUDE_PATH=-I $(INCLUDE_DIR) -I /usr/include/glib-2.0 -I /usr/lib/`uname -m`-linux-gnu/glib-2.0/include/
LIB_PATH=-L $(LIB_DIR)
LIBS=-l mctp -l fmapi -l emapi -l ptrqueue -l arrayutils -l uuid -l timeutils -l cxlstate -l pciutils
TARGET=jack
all: $(TARGET)
$(TARGET): main.c options.o ctrl_handler.o emapi_handler.o fmapi_handler.o cmd_encoder.o
$(CC) $^ $(CFLAGS) $(MACROS) $(INCLUDE_PATH) $(LIB_PATH) $(LIBS) -o $@
cmd_encoder.o: cmd_encoder.c cmd_encoder.h
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
fmapi_handler.o: fmapi_handler.c fmapi_handler.h
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
emapi_handler.o: emapi_handler.c emapi_handler.h
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
ctrl_handler.o: ctrl_handler.c ctrl_handler.h
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
options.o: options.c options.h
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
clean:
rm -rf ./*.o ./*.a $(TARGET)
doc:
doxygen
install: jack
sudo cp $(TARGET) /usr/local/bin/
sudo cp completion.bash /etc/bash_completion.d/$(TARGET)-completion.bash
# List all non file name targets as PHONY
.PHONY: all clean doc install
# Variables
# $^ Will expand to be all the sensitivity list
# $< Will expand to be the frist file in sensitivity list
# $@ Will expand to be the target name (the left side of the ":" )
# -c gcc will compile but not try and link

761
cmd_encoder.c Normal file
View File

@ -0,0 +1,761 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file jack.c
*
* @brief Code file for FM API over TCP CLI
*
* @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>
#include <stdlib.h>
/* autl_prnt_buf()
*/
#include <arrayutils.h>
#include <ptrqueue.h>
#include <fmapi.h>
#include <emapi.h>
/* mctp_init()
* mctp_set_mh()
* mctp_run()
*/
#include <mctp.h>
#include "cmd_encoder.h"
#include "options.h"
/* MACROS ====================================================================*/
#ifdef JACK_VERBOSE
#define INIT unsigned step = 0;
#define ENTER if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_THREADS) printf("%d:%s Enter\n", gettid(), __FUNCTION__);
#define STEP step++; if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step);
#define HEX32(k, i) if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, k, i);
#define INT32(k, i) if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define ERR32(k, i) if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_ERROR) printf("%d:%s STEP: %u ERR: %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define EXIT(rc) if (opts[CLOP_VERBOSITY].u64 & MCTP_VERBOSE_THREADS) printf("%d:%s Exit: %d\n", gettid(), __FUNCTION__,rc);
#else
#define INIT
#define ENTER
#define STEP
#define HEX32(k, i)
#define INT32(k, i)
#define ERR32(k, i)
#define EXIT(rc)
#endif
#define JKLN_CMD_TIMEOUT_SEC 10
#define JKLN_CMD_TIMEOUT_NSEC 0
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
/* GLOBAL VARIABLES ==========================================================*/
/* FUNCTIONS =================================================================*/
struct mctp_action *submit_ctrl(
struct mctp *m,
struct mctp_ctrl_msg *msg,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
)
{
struct timespec delta;
// Initialize variables
delta.tv_sec = JKLN_CMD_TIMEOUT_SEC;
delta.tv_nsec = JKLN_CMD_TIMEOUT_NSEC;
// Set MCTP Control Header fields
msg->hdr.req = 1;
msg->hdr.datagram = 0;
msg->hdr.inst = 0;
msg->len = mctp_len_ctrl((__u8*)&msg->hdr);
// Submit to MCTP library
return mctp_submit(
m, // struct mctp*
MCMT_CONTROL, // [MCMT]
msg, // void* to mctp payload
msg->len+MCLN_CTRL, // Length of mctp payload
retry, // Retry attempts
&delta,
user_data, // To keep with mctp_action
fn_submitted, // fn_submitted
fn_completed, // fn_completed
fn_failed // fn_failed
);
}
struct mctp_action *submit_emapi(
struct mctp *m,
struct emapi_msg *msg,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
)
{
int len;
struct emapi_buf buf;
struct timespec delta;
// Initialize variables
delta.tv_sec = JKLN_CMD_TIMEOUT_SEC;
delta.tv_nsec = JKLN_CMD_TIMEOUT_NSEC;
// Serialize payload
len = emapi_serialize((__u8*)&buf.payload, &msg->obj, emapi_emob_req(msg->hdr.opcode), NULL);
// Set EM API message category as a request
emapi_fill_hdr(&msg->hdr, EMMT_REQ, 0, 0, msg->hdr.opcode, len, msg->hdr.a, msg->hdr.b);
// Serialize EM API Header into buffer
emapi_serialize((__u8*)&buf.hdr, &msg->hdr, EMOB_HDR, NULL);
// Submit to MCTP library
return mctp_submit(
m, // struct mctp*
MCMT_CSE, // [MCMT]
&buf, // void* to mctp payload
msg->hdr.len + EMLN_HDR,// Length of mctp payload
retry, // Retry attempts
&delta,
user_data, // To keep with mctp_action
fn_submitted, // fn_submitted
fn_completed, // fn_completed
fn_failed // fn_failed
);
}
struct mctp_action *submit_fmapi(
struct mctp *m,
struct fmapi_msg *msg,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
)
{
int len;
struct fmapi_buf buf;
struct timespec delta;
// Initialize variables
delta.tv_sec = JKLN_CMD_TIMEOUT_SEC;
delta.tv_nsec = JKLN_CMD_TIMEOUT_NSEC;
// Serialize Object
len = fmapi_serialize((__u8*)&buf.payload, &msg->obj, fmapi_fmob_req(msg->hdr.opcode));
// Fill Header
fmapi_fill_hdr(&msg->hdr, FMMT_REQ, 0, msg->hdr.opcode, 0, len, 0, 0);
// Serialize Header
fmapi_serialize((__u8*)&buf.hdr, &msg->hdr, FMOB_HDR);
// Submit to MCTP library
return mctp_submit(
m, // struct mctp*
MCMT_CXLFMAPI, // [MCMT]
&buf, // void* to mctp payload
msg->hdr.len + FMLN_HDR,// Length of mctp payload
retry, // Retry attempts
&delta,
user_data, // To keep with mctp_action
fn_submitted, // fn_submitted
fn_completed, // fn_completed
fn_failed // fn_failed
);
}
/**
* Prepare an MCTP Message Request from CLI Options
*
* @param mm struct mctp_msg* this is the message to store the request in
* @return 0 upon success, non-zero otherwise
*
* STEPS
* 1: Set buffer pointers
* 3: Command switch
*/
struct mctp_action *submit_cli_request(struct mctp *m, void *user_data)
{
INIT
struct mctp_action *ma;
struct fmapi_msg msg, sub;
struct emapi_msg em;
struct mctp_ctrl_msg mc;
ENTER
// Initialize Variables
ma = NULL;
STEP // 1: Set buffer pointers
STEP // 2: Handle Command
switch (opts[CLOP_CMD].val)
{
case CLCM_NULL:
goto end;
case CLCM_AER:
{
int vcsid, vppbid;
vcsid = 0;
vppbid = 0;
if (opts[CLOP_VCSID].set)
vcsid = opts[CLOP_VCSID].u8; //!< Virtual CXL Switch ID
if (opts[CLOP_VPPBID].set)
vppbid = opts[CLOP_VPPBID].u8; //!< Virtual Pcie-to-PCIe Bridge ID <u8>
if (!opts[CLOP_AER_ERROR].set)
goto end;
if (!opts[CLOP_AER_HEADER].set) //!< TLP Header to place in AER registers, as defined in the PCIe specification
goto end;
fmapi_fill_vsc_aer(&msg, vcsid, vppbid, opts[CLOP_AER_ERROR].u32, opts[CLOP_AER_HEADER].buf);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_BIND:
{
int vcsid, vppbid, ppid, ldid;
vcsid = 0;
vppbid = 0;
ppid = 0;
ldid = 0xFFFF;
if (opts[CLOP_VCSID].set)
vcsid = opts[CLOP_VCSID].u8; //!< Virtual CXL Switch ID
if (opts[CLOP_PPID].set)
ppid = opts[CLOP_PPID].u8; //!< Physical Port ID <u8>
if (opts[CLOP_VPPBID].set)
vppbid = opts[CLOP_VPPBID].u8; //!< Virtual Pcie-to-PCIe Bridge ID <u8>
if (opts[CLOP_LDID].set)
ldid = opts[CLOP_LDID].u16; //!< Logical Device ID <u16>
fmapi_fill_vsc_bind(&msg, vcsid, vppbid, ppid, ldid);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_CONFIG:
{
int ppid, reg, ext, fdbe, type;
ppid = 0;
reg = 0;
ext = 0;
fdbe = 0;
type = 0;
if (opts[CLOP_PPID].set)
ppid = opts[CLOP_PPID].u8; //!< PPB ID: Target PPB physical port
if (opts[CLOP_REGISTER].set)
reg = opts[CLOP_REGISTER].u8; //!< Register Number as defined in PCIe spec
if (opts[CLOP_EXT_REGISTER].set)
ext = opts[CLOP_EXT_REGISTER].u8; //!< Extended Register Number as defined in PCIe spec
if (opts[CLOP_FDBE].set)
fdbe = opts[CLOP_FDBE].u8; //!< First DWord Byte Enable as defined in PCIe spec
else
fdbe = 0x1; //!< First DWord Byte Enable as defined in PCIe spec
if (opts[CLOP_WRITE].set)
type = FMCT_WRITE; //!< Transation type [FMCT]
fmapi_fill_psc_cfg(&msg, ppid, reg, ext, fdbe, type, (__u8*)&opts[CLOP_DATA].u32);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_CONN:
{
emapi_fill_conn(&em, opts[CLOP_PPID].u8, opts[CLOP_DEVICE].u8);
ma = submit_emapi(m, &em, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_DISCONN:
{
emapi_fill_disconn(&em, opts[CLOP_PPID].u8, opts[CLOP_ALL].set);
ma = submit_emapi(m, &em, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_CTRL:
{
int ppid, opcode;
ppid = 0;
opcode = 0;
if (opts[CLOP_PPID].set)
ppid = opts[CLOP_PPID].u8;
switch (opts[CLOP_PORT_CONTROL].val)
{
case CLPC_ASSERT: opcode = FMPO_ASSERT_PERST; break;
case CLPC_DEASSERT: opcode = FMPO_DEASSERT_PERST; break;
case CLPC_RESET: opcode = FMPO_RESET_PPB; break;
default: goto end;
}
fmapi_fill_psc_port_ctrl(&msg, ppid, opcode);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_PORT_UNBIND:
{
int vcsid, vppbid, option;
vcsid = 0;
option = 0;
vppbid = 0xFFFF;
// Prepare Object
if (opts[CLOP_VCSID].set)
vcsid = opts[CLOP_VCSID].u8; //!< Virtual CXL Switch ID
if (opts[CLOP_VPPBID].set)
vppbid = opts[CLOP_VPPBID].u8; //!< Virtual Pcie-to-PCIe Bridge ID <u8>
if (opts[CLOP_UNBIND_MODE].set)
{ //!< Unbind Option [FMUB]
switch(opts[CLOP_UNBIND_MODE].val)
{
case CLPU_WAIT: option = FMUB_WAIT; break;
case CLPU_MANAGED: option = FMUB_MANAGED_HOT_REMOVE; break;
case CLPU_SURPRISE: option = FMUB_SURPRISE_HOT_REMOVE; break;
default: goto end;
}
}
fmapi_fill_vsc_unbind(&msg, vcsid, vppbid, option);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_LD_CONFIG:
{
int ppid, ldid, reg, ext, fdbe, type;
ppid = 0;
ldid = 0;
reg = 0;
ext = 0;
fdbe = 1;
type = FMCT_READ;
// Prepare Object
if (opts[CLOP_PPID].set)
ppid = opts[CLOP_PPID].u8; //!< PPB ID: Target PPB physical port
if (opts[CLOP_REGISTER].set)
reg = opts[CLOP_REGISTER].u8; //!< Register Number as defined in PCIe spec
if (opts[CLOP_EXT_REGISTER].set)
ext = opts[CLOP_EXT_REGISTER].u8; //!< Extended Register Number as defined in PCIe spec
if (opts[CLOP_FDBE].set)
fdbe = opts[CLOP_FDBE].u8; //!< First DWord Byte Enable as defined in PCIe spec
if (opts[CLOP_WRITE].set)
type = FMCT_WRITE; //!< Transation type [FMCT]
if (opts[CLOP_LDID].set)
ldid = opts[CLOP_LDID].u16; //!< Logical Device ID <u16>
fmapi_fill_mpc_cfg(&msg, ppid, ldid, reg, ext, fdbe, type, (__u8*)&opts[CLOP_DATA].u32);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_LD_MEM:
{
int ppid, ldid, len, fdbe, ldbe, type;
__u64 offset;
__u8 *data;
ppid = 0;
ldid = 0;
offset = 0;
len = 0;
fdbe = 0xF; //!< First DWord Byte Enable as defined in PCIe spec
ldbe = 0xF; //!< First DWord Byte Enable as defined in PCIe spec
type = FMCT_READ;
// Prepare Object
if (opts[CLOP_PPID].set)
ppid = opts[CLOP_PPID].u8; //!< PPB ID: Target PPB physical port
if (opts[CLOP_FDBE].set)
fdbe = opts[CLOP_FDBE].u8; //!< First DWord Byte Enable as defined in PCIe spec
if (opts[CLOP_LDBE].set)
ldbe = opts[CLOP_LDBE].u8; //!< Last DWord Byte Enable as defined in PCIe spec
if (opts[CLOP_WRITE].set)
type = FMCT_WRITE; //!< Transation type [FMCT]
if (opts[CLOP_LDID].set)
ldid = opts[CLOP_LDID].u16; //!< Logical Device ID <u16>
if (opts[CLOP_LEN].set)
len = opts[CLOP_LEN].len; //!< Transaction Length in bytes, max of 4 kB
if (opts[CLOP_OFFSET].set)
offset = opts[CLOP_OFFSET].u64; //!< Transaction Offset into target device mem space
data = (__u8*)&opts[CLOP_DATA].u32; //!< Transaction Data: Write data. Only valid for write transactions
if (opts[CLOP_INFILE].set)
data = opts[CLOP_INFILE].buf; //!< Transaction Data: Write data. Only valid for write transactions
fmapi_fill_mpc_mem(&msg, ppid, ldid, offset, len, fdbe, ldbe, type, data);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_MCTP:
break;
case CLCM_MCTP_GET_EID:
{
mctp_ctrl_fill_get_eid(&mc);
ma = submit_ctrl(m, &mc, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_MCTP_GET_TYPE:
{
mctp_ctrl_fill_get_type(&mc);
ma = submit_ctrl(m, &mc, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_MCTP_GET_UUID:
{
mctp_ctrl_fill_get_uuid(&mc);
ma = submit_ctrl(m, &mc, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_MCTP_GET_VER:
{
mctp_ctrl_fill_get_ver(&mc, opts[CLOP_MCTP_TYPE].u8);
ma = submit_ctrl(m, &mc, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_MCTP_SET_EID:
{
mctp_ctrl_fill_set_eid(&mc, opts[CLOP_MCTP_EID].u8);
ma = submit_ctrl(m, &mc, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SET_MSG_LIMIT:
{
fmapi_fill_isc_set_msg_limit(&msg, opts[CLOP_LIMIT].u8);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SET_LD_ALLOCATIONS:
{
int start, num;
start = 0;
num = opts[CLOP_LD_RNG1].num;
if (opts[CLOP_LDID].set)
start = opts[CLOP_LDID].u16;
fmapi_fill_mcc_set_alloc(&sub, start, num, (__u64*)opts[CLOP_LD_RNG1].buf, (__u64*)opts[CLOP_LD_RNG2].buf);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SET_QOS_ALLOCATED:
{
int start, num;
num = opts[CLOP_QOS_ALLOCATED].num;
start = 0;
if (opts[CLOP_LDID].set)
start = opts[CLOP_LDID].u16;
if (!opts[CLOP_QOS_ALLOCATED].set)
goto end;
fmapi_fill_mcc_set_qos_alloc(&sub, start, num, opts[CLOP_QOS_ALLOCATED].buf);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SET_QOS_CONTROL:
{
int epc, ttr, mod, sev, si, rcb, ci;
epc = 0;
ttr = 0;
mod = 0;
sev = 0;
si = 0;
rcb = 0;
ci = 0;
if (opts[CLOP_CONGEST_ENABLE].set)
epc = 1;
if (opts[CLOP_TEMP_THROTTLE].set)
ttr = 1;
if (opts[CLOP_EGRESS_MOD_PCNT].set)
mod = opts[CLOP_EGRESS_MOD_PCNT].u8;
if (opts[CLOP_EGRESS_SEV_PCNT].set)
sev = opts[CLOP_EGRESS_SEV_PCNT].u8;
if (opts[CLOP_BP_SAMPLE_INTVL].set)
si = opts[CLOP_BP_SAMPLE_INTVL].u8;
if (opts[CLOP_REQCMPBASIS].set)
rcb = opts[CLOP_REQCMPBASIS].u16;
if (opts[CLOP_CCINTERVAL].set)
ci = opts[CLOP_CCINTERVAL].u8;
fmapi_fill_mcc_set_qos_ctrl(&sub, epc, ttr, mod, sev, si, rcb, ci);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SET_QOS_LIMIT:
{
int start, num;
num = opts[CLOP_QOS_LIMIT].num;
start = 0;
if (opts[CLOP_LDID].set)
start = opts[CLOP_LDID].u16;
if (!opts[CLOP_QOS_LIMIT].set)
goto end;
fmapi_fill_mcc_set_qos_limit(&sub, start, num, opts[CLOP_QOS_LIMIT].buf);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_BOS:
{
fmapi_fill_isc_bos(&msg);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_IDENTITY:
{
fmapi_fill_isc_id(&msg);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_MSG_LIMIT:
{
fmapi_fill_isc_get_msg_limit(&msg);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_PORT:
{
if (opts[CLOP_PPID].set)
{
if (opts[CLOP_PPID].num > 0)
fmapi_fill_psc_get_ports(&msg, opts[CLOP_PPID].num, opts[CLOP_PPID].buf);
else
fmapi_fill_psc_get_port(&msg, opts[CLOP_PPID].u8);
}
else if (opts[CLOP_ALL].set)
fmapi_fill_psc_get_all_ports(&msg);
else
goto end;
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_LD_ALLOCATIONS:
{
fmapi_fill_mcc_get_alloc(&sub, 0, 0);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_LD_INFO:
{
fmapi_fill_mcc_get_info(&sub);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_QOS_ALLOCATED:
{
__u8 num, start;
num = 255;
start = 0;
if (opts[CLOP_NUM].set)
num = opts[CLOP_NUM].u8;
if (opts[CLOP_LDID].set)
start = opts[CLOP_LDID].u16;
fmapi_fill_mcc_get_qos_alloc(&sub, start, num);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_QOS_CONTROL:
{
fmapi_fill_mcc_get_qos_ctrl(&sub);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_QOS_LIMIT:
{
__u8 num, start;
num = 255;
start = 0;
if (opts[CLOP_NUM].set)
num = opts[CLOP_NUM].u8;
if (opts[CLOP_LDID].set)
start = opts[CLOP_LDID].u16;
fmapi_fill_mcc_get_qos_limit(&sub, start, num);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_QOS_STATUS:
{
fmapi_fill_mcc_get_qos_status(&sub);
fmapi_fill_mpc_tmc(&msg, opts[CLOP_PPID].u8, MCMT_CXLCCI, &sub);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_SWITCH:
{
fmapi_fill_psc_id(&msg);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_DEV:
{
int a = 0;
int b = 0;
if (opts[CLOP_DEVICE].set) {
a = 1;
b = opts[CLOP_DEVICE].u8;
}
if (opts[CLOP_ALL].set) {
a = 0;
}
emapi_fill_listdev(&em, a, b);
ma = submit_emapi(m, &em, 0, user_data, NULL, NULL, NULL);
}
break;
case CLCM_SHOW_VCS:
{
int vcsid = 0;
if (opts[CLOP_VCSID].set)
vcsid = opts[CLOP_VCSID].u8;
fmapi_fill_vsc_get_vcs(&msg, vcsid, 0, 255);
ma = submit_fmapi(m, &msg, 0, user_data, NULL, NULL, NULL);
}
break;
default:
goto end;
}
end:
EXIT(0);
return ma;
}

66
cmd_encoder.h Normal file
View File

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file cmd_encoder.h
*
* @brief Header file for methods to convert the CLI parameters into an
* FM API Request
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Mar 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
#ifndef _CMD_ENCODER_H
#define _CMD_ENCODER_H
/* mctp_state
* mctp_msg
*/
#include <mctp.h>
/* MACROS ====================================================================*/
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
struct mctp_action *submit_ctrl(
struct mctp *m,
struct mctp_ctrl_msg *msg,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
);
struct mctp_action *submit_emapi(
struct mctp *m,
struct emapi_msg *msg,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
);
struct mctp_action *submit_fmapi(
struct mctp *m,
struct fmapi_msg *fm,
int retry,
void *user_data,
void (*fn_submitted)(struct mctp *m, struct mctp_action *a),
void (*fn_completed)(struct mctp *m, struct mctp_action *a),
void (*fn_failed)(struct mctp *m, struct mctp_action *a)
);
struct mctp_action *submit_cli_request(struct mctp *m, void *user_data);
/* GLOBAL VARIABLES ==========================================================*/
#endif //_CMD_ENCODER_H

46
completion.bash Normal file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env /bin/bash
_jack_completions()
{
local cur prev pprev
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
if [ $COMP_CWORD -eq 1 ] ; then
COMPREPLY=($(compgen -W "aer ld mctp port set show" -- $cur))
elif [ $COMP_CWORD -eq 2 ] ; then
case $prev in
aer) ;;
ld) COMPREPLY=($(compgen -W "config mem" -- $cur)) ;;
mctp) ;;
port) COMPREPLY=($(compgen -W "bind config connect control disconnect unbind" -- $cur)) ;;
set) COMPREPLY=($(compgen -W "ld limit qos" -- $cur)) ;;
show) COMPREPLY=($(compgen -W "bos identity ld limit port qos switch vcs" -- $cur)) ;;
*) ;;
esac
elif [ $COMP_CWORD -eq 3 ] ; then
pprev=${COMP_WORDS[COMP_CWORD-2]}
if [ $pprev = "set" ] ; then
case $prev in
ld) COMPREPLY=($(compgen -W "allocations" -- $cur)) ;;
qos) COMPREPLY=($(compgen -W "allocated control limit" -- $cur)) ;;
*) ;;
esac
elif [ $pprev = "show" ] ; then
case $prev in
ld) COMPREPLY=($(compgen -W "allocations info" -- $cur)) ;;
qos) COMPREPLY=($(compgen -W "allocated control limit status" -- $cur)) ;;
*) ;;
esac
fi
fi
}
complete -F _jack_completions jack

196
ctrl_handler.c Normal file
View File

@ -0,0 +1,196 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file ctrl_handler.c
*
* @brief Code file to repond to MCTP Control Messages
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Mar 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
/* gettid()
*/
#define _GNU_SOURCE
#include <unistd.h>
/* printf()
*/
#include <stdio.h>
/* memset()
*/
#include <string.h>
#include <stdlib.h>
/* autl_prnt_buf()
*/
#include <arrayutils.h>
#include <ptrqueue.h>
/* struct mctp
* struct mctp_msg
* struct mctp_ctrl_msg
*/
#include <mctp.h>
#include "ctrl_handler.h"
#include "options.h"
/* MACROS ====================================================================*/
#ifdef JACK_VERBOSE
#define INIT unsigned step = 0;
#define ENTER if (m->verbose & MCTP_VERBOSE_THREADS) printf("%d:%s Enter\n", gettid(), __FUNCTION__);
#define STEP step++; if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step);
#define HEX32(k, i) if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, k, i);
#define INT32(k, i) if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define ERR32(k, i) if (m->verbose & MCTP_VERBOSE_ERROR) printf("%d:%s STEP: %u ERR: %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define EXIT(rc) if (m->verbose & MCTP_VERBOSE_THREADS) printf("%d:%s Exit: %d\n", gettid(), __FUNCTION__,rc);
#else
#define INIT
#define ENTER
#define STEP
#define HEX32(k, i)
#define INT32(k, i)
#define ERR32(k, i)
#define EXIT(rc)
#endif
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
/* GLOBAL VARIABLES ==========================================================*/
/* FUNCTIONS =================================================================*/
/**
* Handle Responses that are MCTP Control Messages
*
* @return 0 upon success. Non zero otherwise.
*
* STEPS
* 1: Set payload pointers
* 2: Validate Response
* 3: Handle opcode
*/
int ctrl_handler(struct mctp *m, struct mctp_msg *mm)
{
INIT
struct mctp_ctrl_msg *msg;
int rv;
ENTER
// Initialize Variables
rv = 1;
STEP // 1: Set payload pointers
msg = (struct mctp_ctrl_msg*) mm->payload;
STEP // 2: Validate Response
// Check MCTP reequest bit
// Check MCTP Instance ID
// Check MCTP Completion Code
if (msg->obj.get_eid_rsp.comp_code != MCCC_SUCCESS)
{
printf("Error: MCTP Control Command %s Failed: %s\n", mccm(msg->hdr.cmd), mccc(msg->obj.get_eid_rsp.comp_code));
goto end;
}
STEP // 3: Handle opcode
switch(msg->hdr.cmd)
{
case MCCM_RESERVED:
break;
case MCCM_SET_ENDPOINT_ID:
{
printf("EID: 0x%02x\n", msg->obj.set_eid_rsp.eid);
}
break;
case MCCM_GET_ENDPOINT_ID:
{
printf("EID: 0x%02x\n", msg->obj.get_eid_rsp.eid);
}
break;
case MCCM_GET_ENDPOINT_UUID:
{
char buf[37];
memset(buf, 0, 37);
// Convert UUID into String for printing
uuid_unparse(msg->obj.get_uuid_rsp.uuid, buf);
printf("MCTP UUID: %s\n", buf);
}
break;
case MCCM_GET_VERSION_SUPPORT:
{
struct mctp_ver *mv;
char buf[11];
for ( int i = 0 ; i < msg->obj.get_ver_rsp.count ; i++)
{
mv = &msg->obj.get_ver_rsp.versions[i];
rv = mctp_sprnt_ver(buf, (struct mctp_version*) mv);
printf("[%02d] %s\n", i, buf);
}
}
break;
case MCCM_GET_MESSAGE_TYPE_SUPPORT:
{
for ( int i = 0 ; i < msg->obj.get_msg_type_rsp.count ; i++)
printf("%02d: %d - %s\n", i, msg->obj.get_msg_type_rsp.list[i], mcmt(msg->obj.get_msg_type_rsp.list[i]));
}
break;
case MCCM_GET_VENDOR_MESSAGE_SUPPORT:
case MCCM_RESOLVE_ENDPOINT_ID:
case MCCM_ALLOCATE_ENDPOINT_IDS:
case MCCM_ROUTING_INFO_UPDATE:
case MCCM_GET_ROUTING_TABLE_ENTRIES:
case MCCM_PREPARE_ENDPOINT_DISCOVERY:
case MCCM_ENDPOINT_DISCOVERY:
case MCCM_DISCOVERY_NOTIFY:
case MCCM_GET_NETWORK_ID:
case MCCM_QUERY_HOP:
case MCCM_RESOLVE_UUID:
case MCCM_QUERY_RATE_LIMIT:
case MCCM_REQUEST_TX_RATE_LIMIT:
case MCCM_UPDATE_RATE_LIMIT:
case MCCM_QUERY_SUPPORTED_INTERFACES:
default: goto end;
}
rv = 0;
end:
// Return mctp_msg to free pool
pq_push(m->msgs, mm);
EXIT(rv)
return rv;
}

35
ctrl_handler.h Normal file
View File

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file ctrl_handler.h
*
* @brief Header file for methods to respond to MCTP Control Messages
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Mar 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
#ifndef _CTRL_HANDLER_H
#define _CTRL_HANDLER_H
/* mctp_state
* mctp_msg
*/
#include <mctp.h>
/* MACROS ====================================================================*/
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
int ctrl_handler(struct mctp *m, struct mctp_msg *mm);
/* GLOBAL VARIABLES ==========================================================*/
#endif //_CTRL_HANDLER_H

158
emapi_handler.c Normal file
View File

@ -0,0 +1,158 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file emapi_handler.c
*
* @brief Code file to handle EM API messages
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Mar 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
/* gettid()
*/
#define _GNU_SOURCE
#include <unistd.h>
/* printf()
*/
#include <stdio.h>
/* memset()
*/
#include <string.h>
#include <stdlib.h>
/* autl_prnt_buf()
*/
#include <arrayutils.h>
#include <ptrqueue.h>
#include <fmapi.h>
#include <emapi.h>
/* mctp_init()
* mctp_set_mh()
* mctp_run()
*/
#include <mctp.h>
#include "options.h"
/* MACROS ====================================================================*/
#ifdef JACK_VERBOSE
#define INIT unsigned step = 0;
#define ENTER if (opts[CLOP_VERBOSITY].u64 & JKVB_CALLSTACK) printf("%d:%s Enter\n", gettid(), __FUNCTION__);
#define STEP step++; if (opts[CLOP_VERBOSITY].u64 & JKVB_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step);
#define HEX32(m, i) if (opts[CLOP_VERBOSITY].u64 & JKVB_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, m, i);
#define INT32(m, i) if (opts[CLOP_VERBOSITY].u64 & JKVB_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, m, i);
#define EXIT(rc) if (opts[CLOP_VERBOSITY].u64 & JKVB_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 // JACK_VERBOSE
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
/* GLOBAL VARIABLES ==========================================================*/
/* FUNCTIONS =================================================================*/
/**
* Handler for all CXL Emulator API Opcodes
*
* @return 0 upon success, 1 otherwise
*
* STEPS
* 1: Set buffer pointers
* 2: Deserialize Header
* 3: Verify Response
* 4: Handle Opcode
*/
int emapi_handler(struct mctp *m, struct mctp_msg *mm)
{
INIT
struct emapi_msg msg;
struct emapi_buf *buf;
int rv;
ENTER
// Initialize variables
rv = 1;
STEP // 1: Set buffer pointers
buf = (struct emapi_buf*) mm->payload;
STEP // 2: Deserialize Header
if ( emapi_deserialize(&msg.hdr, buf->hdr, EMOB_HDR, NULL) == 0 )
goto end;
STEP // 3: Verify response
// Verify EM API Message Type
if (msg.hdr.type != EMMT_RSP)
goto end;
// Check the return code
if (msg.hdr.rc != EMRC_SUCCESS && msg.hdr.rc != EMRC_BACKGROUND_OP_STARTED)
{
printf("Error: %s\n", emrc(msg.hdr.rc));
rv = msg.hdr.rc;
goto end;
}
STEP // 4: Handle Opcode
HEX32("Opcode", msg.hdr.opcode);
switch(msg.hdr.opcode)
{
case EMOP_EVENT: // 0x00
break;
case EMOP_LIST_DEV: // 0x01
{
unsigned i, num;
num = msg.hdr.a;
emapi_deserialize(&msg.obj, buf->payload, EMOB_LIST_DEV, &num);
for ( i = 0 ; i < num ; i++ )
printf("%3d: %s\n", msg.obj.dev[i].id, msg.obj.dev[i].name);
}
break;
case EMOP_CONN_DEV: // 0x02
break;
case EMOP_DISCON_DEV: // 0x03
break;
default:
goto end;
}
rv = 0;
end:
// Return mctp_msg to free pool
pq_push(m->msgs, mm);
EXIT(rv)
return rv;
}

35
emapi_handler.h Normal file
View File

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file emapi_handler.h
*
* @brief Header file for methods to respond to CXL Emulator API commands
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Mar 2024
* @author Barrett Edwards <code@jrlabs.io>
*
*/
/* INCLUDES ==================================================================*/
#ifndef _EMAPI_HANDLER_H
#define _EMAPI_HANDLER_H
/* mctp_state
* mctp_msg
*/
#include <mctp.h>
/* MACROS ====================================================================*/
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
int emapi_handler(struct mctp *m, struct mctp_msg *mm);
/* GLOBAL VARIABLES ==========================================================*/
#endif //_EMAPI_HANDLER_H

1157
fmapi_handler.c Normal file

File diff suppressed because it is too large Load Diff

38
fmapi_handler.h Normal file
View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file fmapi_handler.h
*
* @brief Header 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 ==================================================================*/
#ifndef _FMAPI_HANDLER_H
#define _FMAPI_HANDLER_H
/* mctp_state
* mctp_msg
*/
#include <mctp.h>
/* MACROS ====================================================================*/
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
int fmapi_handler(struct mctp *m, struct mctp_msg *mm, struct mctp_msg *req);
int fmapi_update(struct mctp *m, struct mctp_action *ma);
/* GLOBAL VARIABLES ==========================================================*/
extern struct cxl_switch *cxls;
#endif //_FMAPI_HANDLER_H

392
main.c Normal file
View File

@ -0,0 +1,392 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file jack.c
*
* @brief Code file for FM API over TCP CLI
*
* @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 <stdlib.h>
/* printf()
*/
#include <stdio.h>
/* memset()
*/
#include <string.h>
/* sem_t
* sem_init()
* sem_timedwait()
*/
#include <semaphore.h>
#include <errno.h>
/* autl_prnt_buf()
*/
#include <arrayutils.h>
#include <ptrqueue.h>
#include <timeutils.h>
#include <fmapi.h>
#include <emapi.h>
#include <cxlstate.h>
/* mctp_init()
* mctp_set_mh()
* mctp_run()
*/
#include <mctp.h>
#include "ctrl_handler.h"
#include "emapi_handler.h"
#include "fmapi_handler.h"
#include "cmd_encoder.h"
#include "options.h"
/* MACROS ====================================================================*/
#ifdef JACK_VERBOSE
#define VERBOSE(v, m, t) ({ if(opts[CLOP_VERBOSITY].u64 & v) printf("%d:%s %s\n", t, __FUNCTION__, m ); })
#define VERBOSE_INT(v, m, t, i) ({ if(opts[CLOP_VERBOSITY].u64 & v) printf("%d:%s %s %d\n", t, __FUNCTION__, m, i); })
#define VERBOSE_STR(v, m, t, s) ({ if(opts[CLOP_VERBOSITY].u64 & v) printf("%d:%s %s %s\n", t, __FUNCTION__, m, s); })
#else
#define VERBOSE(v, m, t)
#define VERBOSE_INT(v, m, t, i)
#define VERBOSE_STR(v, m, t, s)
#endif // JACK_VERBOSE
#ifdef JACK_VERBOSE
#define INIT unsigned step = 0;
#define ENTER if (m->verbose & MCTP_VERBOSE_THREADS) printf("%d:%s Enter\n", gettid(), __FUNCTION__);
#define STEP step++; if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step);
#define HEX32(k, i) if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, k, i);
#define INT32(k, i) if (m->verbose & MCTP_VERBOSE_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define ERR32(k, i) if (m->verbose & MCTP_VERBOSE_ERROR) printf("%d:%s STEP: %u ERR: %s: %d\n", gettid(), __FUNCTION__, step, k, i);
#define EXIT(rc) if (m->verbose & MCTP_VERBOSE_THREADS) printf("%d:%s Exit: %d\n", gettid(), __FUNCTION__,rc);
#else
#define INIT
#define ENTER
#define STEP
#define HEX32(k, i)
#define INT32(k, i)
#define ERR32(k, i)
#define EXIT(rc)
#endif // JACK_VERBOSE
#define JKLN_PORTS 32
#define JKLN_VCSS 32
#define JKLN_VPPBS 256
#define JKLN_RSP_MSG_N 13
/* ENUMERATIONS ==============================================================*/
/* STRUCTS ===================================================================*/
/* PROTOTYPES ================================================================*/
/* GLOBAL VARIABLES ==========================================================*/
struct cxl_switch *cxls;
/* FUNCTIONS =================================================================*/
int simple_handler(struct mctp *m, struct mctp_action *ma)
{
m->dummy = 0;
if (ma->sem != NULL)
sem_post(ma->sem);
return 0;
}
int init_switch(struct mctp *m)
{
INIT
struct mctp_action *ma;
struct cxl_port *p;
struct fmapi_msg msg, sub;
ENTER
int rv;
rv = 1;
ma = NULL;
STEP // 1: ISC - Identity
fmapi_fill_isc_id(&msg);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
STEP // 2: ISC - Set msg limit
fmapi_fill_isc_set_msg_limit(&msg, JKLN_RSP_MSG_N);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
STEP // 3: ISC - BOS
fmapi_fill_isc_bos(&msg);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
STEP // 4: PSC - Identify Switch Device
fmapi_fill_psc_id(&msg);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
STEP // 5: PSC - Get Port Status
for ( int i = 0 ; i < cxls->num_ports ; i++)
{
fmapi_fill_psc_get_port(&msg, i);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
}
STEP // 6: VSC - Get VCS Status
for ( int i = 0 ; i < cxls->num_vcss ; i++)
{
fmapi_fill_vsc_get_vcs(&msg, i, 0, 255);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
}
STEP // 7; PCI Config Space - For each port, get first 64 Bytes of config space
for ( int i = 0 ; i < cxls->num_ports ; i++)
{
p = &cxls->ports[i];
if (!p->prsnt)
continue;
for ( int k = 0 ; k < 64 ; k+=4)
{
fmapi_fill_psc_cfg(&msg, i, k, 0, 0xF, FMCT_READ, NULL);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
}
}
STEP // 8: MCC - For each port, if an MLD device, fetch MCC data
for ( int i = 0 ; i < cxls->num_ports ; i++)
{
p = &cxls->ports[i];
if (p->dt != FMDT_CXL_TYPE_3_POOLED)
continue;
// MCC - Get Info
fmapi_fill_mcc_get_info(&sub);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
// MCC - Get LD Alloc
fmapi_fill_mcc_get_alloc(&sub, 0, 0);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
// MCC - Get QoS Control
fmapi_fill_mcc_get_qos_ctrl(&sub);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
// MCC - Get QoS BW Alloc
fmapi_fill_mcc_get_qos_alloc(&sub, 0, 0);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
// MCC - Get QoS BW Limit
fmapi_fill_mcc_get_qos_limit(&sub, 0, 0);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
// MCC- - Get QoS Status
fmapi_fill_mcc_get_qos_status(&sub);
fmapi_fill_mpc_tmc(&msg, i, MCMT_CXLCCI, &sub);
if ( (ma = submit_fmapi(m, &msg, 0, NULL, NULL, NULL, NULL)) == NULL)
goto fail;
fmapi_update(m, ma);
}
rv = 0;
goto end;
fail:
printf("ERR: submit_fmapi() returned NULL. rv: %d\n", rv);
end:
EXIT(rv)
return rv;
}
void list(struct mctp *m)
{
m->dummy = 0;
printf("list\n");
}
/**
* The Jack main run function
*/
void run(struct mctp *m)
{
struct mctp_action *ma;
// Initialize variables
ma = NULL;
// 1: If no command then exit
if ( !opts[CLOP_CMD].set )
goto end;
// Initialize cached copy of remote switch state
if (opts[CLOP_NO_INIT].set == 0)
init_switch(m);
if (opts[CLOP_CMD].val == CLCM_LIST)
list(m);
else
{
// Submit Request
ma = submit_cli_request(m, NULL);
if (ma == NULL)
{
printf("ma Was NULL\n");
if (errno == ETIMEDOUT)
printf("CLI Submit call timed out\n");
goto end;
}
// Print out response
switch(ma->rsp->type)
{
case MCMT_CXLFMAPI: fmapi_handler(m, ma->rsp, ma->req); break;
case MCMT_CSE: emapi_handler(m, ma->rsp); break;
case MCMT_CONTROL: ctrl_handler(m, ma->rsp); break;
default: break;
}
}
end:
return;
}
/**
* jack cli tool main function
*
* STEPS
* 1: Parse CLI options
* 2: Verify Command was requested
* 3: MCTP Init
* 4: Configure MCTP
* 5: Run MCTP
* 6: Free memory
*/
int main(int argc, char* argv[])
{
int rv;
struct mctp *m;
rv = 1;
// STEP 1: Parse CLI options
rv = options_parse(argc,argv);
if (rv != 0)
{
printf("Error: Parse options failed:\n");
goto end;
}
// Initialize global state
cxls = cxls_init(JKLN_PORTS, JKLN_VCSS, JKLN_VPPBS);
// Verify Command was requested
if (!opts[CLOP_CMD].set)
{
printf("Error: No command was selected\n");
rv = 1;
goto end;
}
// MCTP Init
m = mctp_init();
if (m == NULL)
{
printf("Error: mctp_init() failed\n");
rv = 1;
goto end;
}
// Configure MCTP
// Set Message handler functions
mctp_set_handler(m, MCMT_CXLFMAPI, simple_handler);
mctp_set_handler(m, MCMT_CSE, simple_handler);
mctp_set_handler(m, MCMT_CONTROL, simple_handler);
// Set MCTP verbosity levels
mctp_set_verbosity(m, opts[CLOP_MCTP_VERBOSITY].u64);
// Run MCTP
rv = mctp_run(m, opts[CLOP_TCP_PORT].u16, opts[CLOP_TCP_ADDRESS].u32, MCRM_CLIENT, 1, 1);
if (rv != 0)
{
printf("Error: mctp_run() failed: %d\n", rv);
goto stop;
}
// Run Jack main sequence
run(m);
mctp_stop(m);
rv = 0;
stop:
// STEP 6: Free memory
mctp_free(m);
cxls_free(cxls);
options_free(opts);
return rv;
end:
return rv;
};

4717
options.c Normal file

File diff suppressed because it is too large Load Diff

333
options.h Normal file
View File

@ -0,0 +1,333 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
* @file options.h
*
* @brief Header file for CXL Fabric Management CLI options
*
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
*
* @date Jan 2024
* @author Barrett Edwards <code@jrlabs.io>
*
* Macro / Enumeration Prefixes (CL)
* CLAP - CLI Options Parsers Enumeration (AP)
* CLCM - CLI Command Opcod (CM)
* CLMR - CLI Macros (MR)
* CLOP - CLI Option (CL)
* CLPC - Physical Port Control Opcodes (PC)
* CLPU - Port Unbind Mode Options (PU)
*
* Standard key mapping
* -h --help Display Help
* -T --tcp-port Server TCP Port
* -V --verbosity Set Verbosity Flag
* -X --verbosity-hex Set all Verbosity Flags with hex value
* -p --ppid Physical Port ID
* -c --vcsid Virtual CXL Switch ID
* -b --vppbid Virtual PCIe-to-PCIe Bridge ID
* -a --all All of collection
* -l --ldid LD-ID (for MLD devices)
* -w --write Perform a Write transaction
* -n --length Length
* -o --offset Memory Offset
* --data Write Data (up to 4 bytes)
* --infile Filename for input data
* --outfile Filename for output data
*
* Non char key mapping
* 701 - usage
* 702 - version
* 703 - data
* 704 - infile
* 705 - outfile
* 706 - print-options
*/
#ifndef _OPTIONS_H
#define _OPTIONS_H
/* INCLUDES ==================================================================*/
/* __u8
* __u15
* __u32
* __u64
* __s32
*/
#include <linux/types.h>
/* MACROS ====================================================================*/
/**
* CLI Macros (MR)
*
* These are values that don't belong in an enumeration
*/
#define CLMR_MAX_LD_MEM_LEN 4096
#define CLMR_MAX_LD 16
#define CLMR_HELP_COLUMN 30
#define CLMR_MAX_HELP_WIDTH 100
#define CLMR_MAX_NAME_LEN 64
#define CLMR_AER_HEADER_LEN 32
#define DEFAULT_SERVER_PORT 2508
/* ENUMERATIONS ==============================================================*/
/**
* Verbosity Options (VO)
*/
enum _JKVO
{
JKVO_GENERAL = 0,
JKVO_CALLSTACK = 1,
JKVO_STEPS = 2,
JKVO_MAX
};
/**
* Verbosity Bitfield Index (VB)
*/
enum _JKVB
{
JKVB_GENERAL = (0x01 << 0),
JKVB_CALLSTACK = (0x01 << 1),
JKVB_STEPS = (0x01 << 2),
};
/**
* CLI Options Parsers Enumeration (AP)
*
* This enumeration identifies each argp parser. It is used to print options
*/
enum _CLAP
{
CLAP_MAIN = 0,
CLAP_MCTP = 1,
CLAP_SHOW = 2,
CLAP_PORT = 3,
CLAP_SET = 4,
CLAP_LD = 5,
CLAP_AER = 6,
CLAP_SHOW_SWITCH = 7,
CLAP_SHOW_PORT = 8,
CLAP_SHOW_VCS = 9,
CLAP_SHOW_QOS = 10,
CLAP_SHOW_LD = 11,
CLAP_PORT_BIND = 12,
CLAP_PORT_UNBIND = 13,
CLAP_PORT_CONFIG = 14,
CLAP_PORT_CTRL = 15,
CLAP_SET_LD = 16,
CLAP_SET_QOS = 17,
CLAP_LD_CONFIG = 18,
CLAP_LD_MEM = 19,
CLAP_SHOW_QOS_ALLOCATED = 20,
CLAP_SHOW_QOS_CONTROL = 21,
CLAP_SHOW_QOS_LIMIT = 22,
CLAP_SHOW_QOS_STATUS = 23,
CLAP_SHOW_LD_ALLOCATIONS = 24,
CLAP_SHOW_LD_INFO = 25,
CLAP_SET_LD_ALLOCATIONS = 26,
CLAP_SET_QOS_ALLOCATED = 27,
CLAP_SET_QOS_CONTROL = 28,
CLAP_SET_QOS_LIMIT = 29,
CLAP_SHOW_DEV = 30,
CLAP_PORT_CONN = 31,
CLAP_PORT_DISCONN = 32,
CLAP_SHOW_IDENTITY = 33,
CLAP_SHOW_MSG_LIMIT = 34,
CLAP_SET_MSG_LIMIT = 35,
CLAP_SHOW_BOS = 36,
CLAP_MAX
};
/**
* CLI Command Opcode (CM)
*/
enum _CLCM
{
CLCM_NULL = 0,
CLCM_AER = 1,
CLCM_PORT_BIND = 2,
CLCM_PORT_CONFIG = 3,
CLCM_PORT_CTRL = 4,
CLCM_PORT_UNBIND = 5,
CLCM_LD_CONFIG = 6,
CLCM_LD_MEM = 7,
CLCM_MCTP = 8,
CLCM_MCTP_GET_EID = 9,
CLCM_MCTP_GET_TYPE = 10,
CLCM_MCTP_GET_UUID = 11,
CLCM_MCTP_GET_VER = 12,
CLCM_MCTP_SET_EID = 13,
CLCM_SET_LD_ALLOCATIONS = 14,
CLCM_SET_QOS_ALLOCATED = 15,
CLCM_SET_QOS_CONTROL = 16,
CLCM_SET_QOS_LIMIT = 17,
CLCM_SHOW_PORT = 18,
CLCM_SHOW_LD_ALLOCATIONS= 19,
CLCM_SHOW_LD_INFO = 20,
CLCM_SHOW_QOS_ALLOCATED = 21,
CLCM_SHOW_QOS_CONTROL = 22,
CLCM_SHOW_QOS_LIMIT = 23,
CLCM_SHOW_QOS_STATUS = 24,
CLCM_SHOW_SWITCH = 25,
CLCM_SHOW_VCS = 26,
CLCM_SHOW_DEV = 27,
CLCM_PORT_CONN = 28,
CLCM_PORT_DISCONN = 29,
CLCM_SHOW_IDENTITY = 30,
CLCM_SHOW_MSG_LIMIT = 31,
CLCM_SET_MSG_LIMIT = 32,
CLCM_SHOW_BOS = 33,
CLCM_LIST = 34,
CLCM_MAX
};
/**
* CLI Option (OP)
*/
enum _CLOP
{
/* General CLI Options */
CLOP_VERBOSITY = 0, //!< Bit Field <u64>
CLOP_TCP_PORT = 1, //!< TCP Port to connect to <u16>
CLOP_CMD = 2, //!< Command to RUN <val>
CLOP_INFILE = 3, //!< Filename for input <str,buf,len>
/* Hiden Options */
CLOP_PRNT_OPTS = 4, //!< Print Options Array when completed parsing <set>
/* MCTP Options */
CLOP_MCTP_EID = 5, //!< EID value for MCTP Set EID Command <u8>
CLOP_MCTP_TYPE = 6, //!< Type value for MCTP Command Get Ver Command <u8>
/* ID Options */
CLOP_VCSID = 7, //!< Virtual CXL Switch ID <u8>
CLOP_PPID = 8, //!< Physical Port ID <u8>
CLOP_VPPBID = 9, //!< Virtual Pcie-to-PCIe Bridge ID <u8>
CLOP_LDID = 10, //!< Logical Device ID <u16>
CLOP_ALL = 11, //!< Perform aciton on all of collection <set>
/* Port Options */
CLOP_UNBIND_MODE = 12, //!< Port Unbind Option [CLPU] <val>
CLOP_PORT_CONTROL = 13, //!< Action to perform [CLPC] <val>
/* Config & Memory Options */
CLOP_REGISTER = 14, //!< Register number <u8>
CLOP_EXT_REGISTER = 15, //!< Extended Register number <u8>
CLOP_FDBE = 16, //!< First Dword Byte Enable <u8>
CLOP_LDBE = 17, //!< First Dword Byte Enable <u8>
CLOP_WRITE = 18, //!< Perform a write transacion <set>
CLOP_OFFSET = 19, //!< Offset into a buffer address space <u64>
CLOP_LEN = 20, //!< Length of data parameter <len>
/* LD Options */
CLOP_LD_RNG1 = 21, //!< LD Allocations Range1 Array <num,len,buf>
CLOP_LD_RNG2 = 22, //!< LD Allocations Range2 Array <num,len,buf>
/* QoS Options */
CLOP_CONGEST_ENABLE = 23, //!< Egress Port Congestion Enable <set>
CLOP_TEMP_THROTTLE = 24, //!< Temporary Throughput Reduction Enable <set>
CLOP_EGRESS_MOD_PCNT = 25, //!< Egress Moderate Percentage <u8>
CLOP_EGRESS_SEV_PCNT = 26, //!< Egress Severe Percentage <u8>
CLOP_BP_SAMPLE_INTVL = 27, //!< Backpressure Sample Interval <u8>
CLOP_REQCMPBASIS = 28, //!< ReqCmpBasis <u16>
CLOP_CCINTERVAL = 29, //!< Completion Collection Interval <u8>
CLOP_QOS_ALLOCATED = 30, //!< QoS BW Allocation Fraction list <num,len,buf>
CLOP_QOS_LIMIT = 31, //!< QoS BW Limit Fraction list <num,len,buf>
/* AER Options */
CLOP_AER_ERROR = 32, //!< AER Error (4 Byte HEX) <u32>
CLOP_AER_HEADER = 33, //!< AER TLP Header (32 Byte HEX String) <num,len,buf>
CLOP_DATA = 34, //!< Immediate Data for Write transaction <u32>
CLOP_OUTFILE = 35, //!< Filename for output <str>
CLOP_MCTP_VERBOSITY = 36, //!< Verbosity setting for MCTP library
CLOP_DEVICE = 37, //!< Device ID <u8>
CLOP_NUM = 38, //!< Number of items <u8>
CLOP_LIMIT = 39, //!< Message Response Limit <u8>
CLOP_TCP_ADDRESS = 40, //!< TCP Address to connect to <u32>
CLOP_NO_INIT = 41, //!< Do not initialize local state at start up
CLOP_MAX
};
/**
* Physical Port Control Opcodes (PC)
*
* CXL 2.0 v1.0 Table 93
*/
enum _CLPC
{
CLPC_ASSERT = 0,
CLPC_DEASSERT = 1,
CLPC_RESET = 2,
CLPC_MAX
};
/**
* Port Unbind Mode Options (PU)
*
* CXL 2.0 v1.0 Table 101
*/
enum _CLPU
{
CLPU_WAIT = 0,
CLPU_MANAGED = 1,
CLPU_SURPRISE = 2,
CLPU_MAX
};
/* STRUCTS ===================================================================*/
/**
* CLI Option Struct
*
* Each command line parameter is stored in one of these objects
*/
struct opt
{
int set; //!< Not set (0), set (1)
__u8 u8; //!< Unsigned char value
__u16 u16; //!< Unsigned long value
__u32 u32; //!< Unsigned long value
__u64 u64; //!< Unsigned long long value
__s32 val; //!< Generic signed value
__u64 num; //!< Number of items
__u64 len; //!< Data Buffer Length
char *str; //!< String value
__u8 *buf; //!< Data buffer
};
/* GLOBAL VARIABLES ==========================================================*/
/**
* Global varible to store parsed CLI options
*/
extern struct opt *opts;
/* PROTOTYPES ================================================================*/
/**
* Free allocated memory by option parsing proceedure
*
* @return 0 upon success. Non zero otherwise
*/
int options_free(struct opt *opts);
/**
* Parse command line options
*/
int options_parse(int argc, char *argv[]);
#endif //ifndef _OPTIONS_H

151
testbench.bash Executable file
View File

@ -0,0 +1,151 @@
#!/bin/bash
echo -e \\n------------------------------------------------------------------------------
echo -e 1: Show help menu for each command \\n
set -x
jack
jack aer
jack ld
jack ld cfg
jack ld mem
jack mctp
jack port
jack port bind
jack port config
jack port control
jack port unbind
jack set ld
jack set ld allocations
jack set qos
jack set qos allocated
jack set qos control
jack set qos limit
jack show
jack show ld
jack show ld allocations
jack show ld info
jack show port -h
jack show qos
jack show qos allocated
jack show qos control
jack show qos limit
jack show qos status
jack show switch -h
jack show vcs -h
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 2: Show Commands \\n
set -x
jack show id
jack show bos
jack show limit
jack show switch
jack show port -a
jack show vcs -a
jack show ld info -p 1
jack show ld allocations -p 1
jack show qos status -p 1
jack show qos control -p 1
jack show qos allocated -p 1
jack show qos limit -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 3: Port CXL.io CFG commands \\n
set -x
jack port config -p 0 -r 0 -e 0 -f 0xF
jack port config -p 0 -r 0 -e 0 -f 0xF -w --data 0xa1a2a3a4
jack port config -p 0 -r 0 -e 0 -f 0xF
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 3: LD CXL.io CFG commands \\n
set -x
jack ld config -p 1 -l 0 -r 0 -e 0 -f 0xF
jack ld config -p 1 -l 0 -r 0 -e 0 -f 0xF -w --data 0xa1a2a3a4
jack ld config -p 1 -l 0 -r 0 -e 0 -f 0xF
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 4: Port Control \\n
set -x
jack show port -p 1
jack port ctrl -p 1 --assert-perst
jack show port -p 1
jack port ctrl -p 1 --deassert-perst
jack show port -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 5: Port Bind/Unbind \\n
set -x
jack show port -p 1
jack port bind -p 1 -l 0 -c 0 -b 0
jack show port -p 1
jack show vcs -c 0
jack port unbind -c 0 -b 0
jack show port -p 1
jack show vcs -c 0
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 6: Set LD Allocations \\n
set -x
jack show ld allocations -p 1
jack set ld allocations -p 1 --range1 0,1,2,3,4,5,6,7,8,9,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f --range2 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
jack show ld allocations -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 7: Set QoS Allocated \\n
set -x
jack show qos allocated -p 1
jack set qos allocated -p 1 -f 0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf
jack show qos allocated -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 8: Set QoS Limit \\n
set -x
jack show qos limit -p 1
jack set qos limit -p 1 -f 0xf,0xe,0xd,0xc,0xb,0xa,9,8,7,6,5,4,3,2,1,0
jack show qos limit -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 9: Set QoS Control \\n
set -x
jack show qos control -p 1
jack set qos control -p 1 -m 52 -s 63 -k 18 -q 21 -i 74
jack show qos control -p 1
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 10: AER \\n
set -x
jack aer -c 0 -b 0 -e 0xc1c2c3c4 -t 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F
set +x
echo -e \\n------------------------------------------------------------------------------
echo -e 11: MCTP \\n
set -x
jack mctp --get-eid
jack mctp --get-uuid
jack mctp --get-type
jack mctp --get-ver 0x7
set +x