Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ conf.set10('HAVE_STRUCT_MCTP_FQ_ADDR',
cc.has_type('struct mctp_fq_addr', prefix: '#include <linux/mctp.h>'),
description: 'Is struct mctp_fq_addr available?'
)
conf.set10('HAVE_IFLA_MCTP_PHYS_BINDING',
cc.has_header_symbol('linux/if_link.h', 'IFLA_MCTP_PHYS_BINDING'),
description: 'Is IFLA_MCTP_PHYS_BINDING enum member available?'
)
conf.set10('MCTPD_RECOVER_NIL_UUID',
get_option('unsafe-recover-nil-uuid'),
description: 'Consider a nil UUID to be valid for endpoint recovery purposes',
Expand Down
18 changes: 18 additions & 0 deletions src/mctp-control-spec.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,21 @@ static inline void mctp_ctrl_msg_hdr_init_resp(struct mctp_ctrl_msg_hdr *resp,
resp->command_code = req.command_code;
resp->rq_dgram_inst = (req.rq_dgram_inst & RQDI_IID_MASK) | RQDI_RESP;
}

/* MCTP IDs and Codes from DMTF specification
* "DSP0239 Management Component Transport Protocol (MCTP) IDs and Codes"
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0239_1.11.1.pdf
*/
enum mctp_phys_binding {
MCTP_PHYS_BINDING_UNSPEC = 0x00,
MCTP_PHYS_BINDING_SMBUS = 0x01,
MCTP_PHYS_BINDING_PCIE_VDM = 0x02,
MCTP_PHYS_BINDING_USB = 0x03,
MCTP_PHYS_BINDING_KCS = 0x04,
MCTP_PHYS_BINDING_SERIAL = 0x05,
MCTP_PHYS_BINDING_I3C = 0x06,
MCTP_PHYS_BINDING_MMBI = 0x07,
MCTP_PHYS_BINDING_PCC = 0x08,
MCTP_PHYS_BINDING_UCIE = 0x09,
MCTP_PHYS_BINDING_VENDOR = 0xFF,
};
26 changes: 22 additions & 4 deletions src/mctp-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>
#include <linux/netdevice.h>

#include "mctp-control-spec.h"
#include "mctp-netlink.h"
#include "mctp.h"
#include "mctp-util.h"
Expand All @@ -29,6 +30,7 @@ struct linkmap_entry {
uint32_t min_mtu;
uint32_t max_mtu;
uint32_t hwaddr_len;
uint8_t phys_binding;

mctp_eid_t *local_eids;
size_t num_local;
Expand Down Expand Up @@ -59,7 +61,8 @@ static void sort_linkmap(mctp_nl *nl);
static int linkmap_add_entry(mctp_nl *nl, struct ifinfomsg *info,
const char *ifname, size_t ifname_len,
uint32_t net, bool up, uint32_t min_mtu,
uint32_t max_mtu, size_t hwaddr_len);
uint32_t max_mtu, size_t hwaddr_len,
uint8_t phys_binding);
static struct linkmap_entry *entry_byindex(const mctp_nl *nl, int index);

static int open_nl_socket(void)
Expand Down Expand Up @@ -727,6 +730,7 @@ static int parse_getlink_dump(mctp_nl *nl, struct nlmsghdr *nlh, uint32_t len)
char *ifname = NULL;
size_t ifname_len, rlen, nlen, mlen, hwaddr_len;
uint32_t net, min_mtu = 0, max_mtu = 0;
uint8_t phys_binding;
bool up;

if (nlh->nlmsg_type == NLMSG_DONE)
Expand Down Expand Up @@ -785,11 +789,14 @@ static int parse_getlink_dump(mctp_nl *nl, struct nlmsghdr *nlh, uint32_t len)
hwaddr_len = 0;
mctp_get_rtnlmsg_attr(IFLA_ADDRESS, rta, rlen, &hwaddr_len);

/* TODO: media type */
/* Treat missing physical binding type attribute as UNSPEC */
phys_binding = MCTP_PHYS_BINDING_UNSPEC;
mctp_get_rtnlmsg_attr_u8(IFLA_MCTP_PHYS_BINDING, rt_mctp, mlen,
&phys_binding);

up = info->ifi_flags & IFF_UP;
linkmap_add_entry(nl, info, ifname, ifname_len, net, up,
min_mtu, max_mtu, hwaddr_len);
min_mtu, max_mtu, hwaddr_len, phys_binding);
}
// Not done.
return 1;
Expand Down Expand Up @@ -1068,6 +1075,15 @@ int mctp_nl_hwaddr_len_byindex(const mctp_nl *nl, int index,
return 0;
}

uint8_t mctp_nl_phys_binding_byindex(const mctp_nl *nl, int index)
{
struct linkmap_entry *entry = entry_byindex(nl, index);
if (!entry) {
return MCTP_PHYS_BINDING_UNSPEC;
}
return entry->phys_binding;
}

mctp_eid_t *mctp_nl_addrs_byindex(const mctp_nl *nl, int index, size_t *ret_num)
{
struct linkmap_entry *entry = entry_byindex(nl, index);
Expand Down Expand Up @@ -1151,7 +1167,8 @@ bool mctp_nl_if_exists(const mctp_nl *nl, int ifindex)
static int linkmap_add_entry(mctp_nl *nl, struct ifinfomsg *info,
const char *ifname, size_t ifname_len,
uint32_t net, bool up, uint32_t min_mtu,
uint32_t max_mtu, size_t hwaddr_len)
uint32_t max_mtu, size_t hwaddr_len,
uint8_t phys_binding)
{
struct linkmap_entry *entry;
size_t newsz;
Expand Down Expand Up @@ -1192,6 +1209,7 @@ static int linkmap_add_entry(mctp_nl *nl, struct ifinfomsg *info,
entry->max_mtu = max_mtu;
entry->min_mtu = min_mtu;
entry->hwaddr_len = hwaddr_len;
entry->phys_binding = phys_binding;
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions src/mctp-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <linux/if.h>
#include <linux/rtnetlink.h>

#include "mctp-control-spec.h"
#include "mctp.h"

struct mctp_nl;
Expand Down Expand Up @@ -83,6 +84,8 @@ uint32_t mctp_nl_max_mtu_byindex(const mctp_nl *nl, int index);
/* Returns negative errno on failure */
int mctp_nl_hwaddr_len_byindex(const mctp_nl *nl, int index,
size_t *ret_hwaddr_len);
/* Returns interface physical binding, or MCTP_PHYS_BINDING_UNSPEC if bad index */
uint8_t mctp_nl_phys_binding_byindex(const mctp_nl *nl, int index);
/* Caller to free */
mctp_eid_t *mctp_nl_addrs_byindex(const mctp_nl *nl, int index,
size_t *ret_num);
Expand Down
11 changes: 11 additions & 0 deletions src/mctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,22 @@ struct sockaddr_mctp_ext {
enum {
IFLA_MCTP_UNSPEC,
IFLA_MCTP_NET,
IFLA_MCTP_PHYS_BINDING,
__IFLA_MCTP_MAX,
};

#define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1)

#else /* IFLA_MCTP_MAX */

#if !HAVE_IFLA_MCTP_PHYS_BINDING
enum {
IFLA_MCTP_PHYS_BINDING = IFLA_MCTP_NET + 1,
};
#undef IFLA_MCTP_MAX
#define IFLA_MCTP_MAX IFLA_MCTP_PHYS_BINDING
#endif /* HAVE_IFLA_MCTP_PHYS_BINDING */

#endif /* IFLA_MCTP_MAX */

/* setsockopt(2) options */
Expand Down
130 changes: 130 additions & 0 deletions src/mctpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,14 @@ static const struct role roles[] = {
},
};

enum discovery_state {
DISCOVERY_UNSUPPORTED,
DISCOVERY_DISCOVERED,
DISCOVERY_UNDISCOVERED,
};

struct link {
enum discovery_state discovered;
bool published;
int ifindex;
enum endpoint_role role;
Expand Down Expand Up @@ -777,6 +784,9 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
warnx("ERR: cannot add bus owner to object lists");
}

if (link_data->discovered != DISCOVERY_UNSUPPORTED) {
link_data->discovered = DISCOVERY_DISCOVERED;
}
resp->status =
SET_MCTP_EID_ASSIGNMENT_STATUS(MCTP_SET_EID_ACCEPTED) |
SET_MCTP_EID_ALLOCATION_STATUS(MCTP_SET_EID_POOL_NONE);
Expand All @@ -786,6 +796,20 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
return reply_message(ctx, sd, resp, resp_len, addr);

case MCTP_SET_EID_DISCOVERED:
if (link_data->discovered == DISCOVERY_UNSUPPORTED) {
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
resp_len = sizeof(struct mctp_ctrl_resp);
return reply_message(ctx, sd, resp, resp_len, addr);
}

link_data->discovered = DISCOVERY_DISCOVERED;
resp->status =
SET_MCTP_EID_ASSIGNMENT_STATUS(MCTP_SET_EID_REJECTED) |
SET_MCTP_EID_ALLOCATION_STATUS(MCTP_SET_EID_POOL_NONE);
resp->eid_set = req->eid;
resp->eid_pool_size = 0;
return reply_message(ctx, sd, resp, resp_len, addr);

case MCTP_SET_EID_RESET:
// unsupported
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
Expand Down Expand Up @@ -948,6 +972,97 @@ handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
return reply_message(ctx, sd, resp, resp_len, addr);
}

static int handle_control_prepare_endpoint_discovery(
struct ctx *ctx, int sd, const struct sockaddr_mctp_ext *addr,
const uint8_t *buf, const size_t buf_size)
{
struct mctp_ctrl_msg_hdr *req = NULL;
struct mctp_ctrl_resp_prepare_discovery respi = { 0 }, *resp = &respi;
struct link *link_data;

if (buf_size < sizeof(*req)) {
warnx("short Prepare for Endpoint Discovery message");
return -ENOMSG;
}

link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
if (!link_data) {
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
return -ENOENT;
}

if (link_data->role == ENDPOINT_ROLE_BUS_OWNER) {
// ignore message if we are bus owner
return 0;
}

req = (void *)buf;
resp = (void *)resp;
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);

if (link_data->discovered == DISCOVERY_UNSUPPORTED) {
warnx("received prepare for discovery request to unsupported interface %d",
addr->smctp_ifindex);
resp->completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD;
return reply_message_phys(ctx, sd, resp,
sizeof(struct mctp_ctrl_resp), addr);
}

if (link_data->discovered == DISCOVERY_DISCOVERED) {
link_data->discovered = DISCOVERY_UNDISCOVERED;
warnx("clear discovered flag of interface %d",
addr->smctp_ifindex);
}

// we need to send using physical addressing, no entry in routing table yet
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
}

static int
handle_control_endpoint_discovery(struct ctx *ctx, int sd,
const struct sockaddr_mctp_ext *addr,
const uint8_t *buf, const size_t buf_size)
{
struct mctp_ctrl_msg_hdr *req = NULL;
struct mctp_ctrl_resp_endpoint_discovery respi = { 0 }, *resp = &respi;
struct link *link_data;

if (buf_size < sizeof(*req)) {
warnx("short Endpoint Discovery message");
return -ENOMSG;
}

link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
if (!link_data) {
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
return -ENOENT;
}

if (link_data->role == ENDPOINT_ROLE_BUS_OWNER) {
// ignore message if we are bus owner
return 0;
}

if (link_data->discovered == DISCOVERY_UNSUPPORTED) {
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
return reply_message(ctx, sd, resp,
sizeof(struct mctp_ctrl_resp), addr);
}

if (link_data->discovered == DISCOVERY_DISCOVERED) {
// if we are already discovered (i.e, assigned an EID), then no reply
return 0;
}

req = (void *)buf;
resp = (void *)resp;
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);

// we need to send using physical addressing, no entry in routing table yet
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
}

static int handle_control_unsupported(struct ctx *ctx, int sd,
const struct sockaddr_mctp_ext *addr,
const uint8_t *buf, const size_t buf_size)
Expand Down Expand Up @@ -1030,6 +1145,14 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
rc = handle_control_resolve_endpoint_id(ctx, sd, &addr, buf,
buf_size);
break;
case MCTP_CTRL_CMD_PREPARE_ENDPOINT_DISCOVERY:
rc = handle_control_prepare_endpoint_discovery(ctx, sd, &addr,
buf, buf_size);
break;
case MCTP_CTRL_CMD_ENDPOINT_DISCOVERY:
rc = handle_control_endpoint_discovery(ctx, sd, &addr, buf,
buf_size);
break;
default:
if (ctx->verbose) {
warnx("Ignoring unsupported command code 0x%02x",
Expand Down Expand Up @@ -3905,10 +4028,13 @@ static int add_interface(struct ctx *ctx, int ifindex)
return -ENOENT;
}

uint8_t phys_binding = mctp_nl_phys_binding_byindex(ctx->nl, ifindex);

struct link *link = calloc(1, sizeof(*link));
if (!link)
return -ENOMEM;

link->discovered = DISCOVERY_UNSUPPORTED;
link->published = false;
link->ifindex = ifindex;
link->ctx = ctx;
Expand Down Expand Up @@ -3937,6 +4063,10 @@ static int add_interface(struct ctx *ctx, int ifindex)
bus_link_owner_vtable, link);
}

if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM) {
link->discovered = DISCOVERY_UNDISCOVERED;
}

link->published = true;
rc = emit_interface_added(link);
if (rc < 0) {
Expand Down
Loading