[ofa-general] [PATCHv2] ibsim: Support short RMPP packets

Hal Rosenstock hrosenstock at xsigo.com
Thu Jun 19 07:35:28 PDT 2008


ibsim: Support for short RMPP packets (up thru 256 bytes total)

Changes from v1:
- Added length to simulation header (by reducing context size so as not
to break ABI) and encoded length on sends and decoded and checked
lengths on receive
- Restored short/partial packet read check in umad2sim_read
- In umad2sim_write, fixed setting of umad->length
- Eliminated sim_req256 typedef

Signed-off-by: Hal Rosenstock <hal at xsigo.com>

diff --git a/TODO b/TODO
index 616ed71..b385ade 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 * transaction management
   - multiple transactions per client
   - hops simulation
-  - RMPP
+  - long RMPP
 * more attributes handled
 * MKey support
 * cleaner (less) debug/warning messages
diff --git a/ibsim/ibsim.c b/ibsim/ibsim.c
index e4ab6bc..cde9ac5 100644
--- a/ibsim/ibsim.c
+++ b/ibsim/ibsim.c
@@ -492,9 +492,9 @@ static int sim_read_pkt(int fd, int client)
 		if (!dcl)
 			continue;
 
-		VERB("%s %d bytes (%zu) to client %d fd %d",
+		VERB("%s %d bytes to client %d fd %d",
 		     dcl == cl ? "replying" : "forwarding",
-		     size, sizeof(struct sim_request), dcl->id, dcl->fd);
+		     size, dcl->id, dcl->fd);
 
 		// reply
 		ret = write(dcl->fd, buf, size);
diff --git a/ibsim/sim_mad.c b/ibsim/sim_mad.c
index 675d95b..28fdd52
--- a/ibsim/sim_mad.c
+++ b/ibsim/sim_mad.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
  *
  * This file is part of ibsim.
  *
@@ -1128,14 +1129,14 @@ Smpfn *get_handle_fn(ib_rpc_t rpc, int response)
 		return fn;
 	}
 
-	return 0;		// No MGTCLASS matched .
+	return 0;		// No MGTCLASS matched.
 }
 
 int process_packet(Client * cl, void *p, int size, Client ** dcl)
 {
 	struct sim_request *r = p;
 	Port *port;
-	uint8_t data[256];
+	uint8_t data[MAD_BLOCK_SIZE];
 	int status, tlid, tqp;
 	int response;
 	Smpfn *fn;
@@ -1144,9 +1145,10 @@ int process_packet(Client * cl, void *p, int size, Client ** dcl)
 
 	*dcl = cl;
 
-	DEBUG("client %d, size %d", cl->id, size);
-	if (size != sizeof(*r)) {
-		IBWARN("bad packet size %d (!= %zu)", size, sizeof(*r));
+	DEBUG("client %d size %d", cl->id, size);
+	if (size > sizeof(*r) + MAD_BLOCK_SIZE) {
+		IBWARN("unsupported packet size %d (> %zu)", size,
+		       sizeof(*r) + MAD_BLOCK_SIZE);
 		return -1;
 	}
 
@@ -1183,7 +1185,7 @@ int process_packet(Client * cl, void *p, int size, Client ** dcl)
 		VERB("forward pkt to client %d pid %d attr %d",
 		     (*dcl)->id, (*dcl)->pid, rpc.attr.id);
 		forward_MAD(r->mad, &rpc, &path);
-		return sizeof(*r);	// forward only
+		return size;		// forward only
 	}
 
 	if (port->errrate && (random() % 100) < port->errrate) {
@@ -1214,12 +1216,12 @@ int process_packet(Client * cl, void *p, int size, Client ** dcl)
 		VERB("PKT roll back did not succeed");
 		goto _dropped;
 	}
-	return sizeof(*r);
+	return sizeof(*r) + MAD_BLOCK_SIZE;
 
   _dropped:
 	r->status = htonl(110);
 	*dcl = cl;
-	return sizeof(*r);
+	return sizeof(*r) + MAD_BLOCK_SIZE;
 }
 
 static int encode_trap128(Port * port, char *data)
@@ -1279,48 +1281,60 @@ static int encode_trap_header(char *buf)
 
 int send_trap(Port * port, int trapnum)
 {
-	struct sim_request req;
+	struct sim_request *req;
 	Client *cl;
 	int ret, lid = port->lid;
-	char *data = req.mad + 64;	/* data offset */
 	EncodeTrapfn *encode_trapfn = encodetrap[trapnum];
 	Port *destport;
 
 	if (!encode_trapfn) {
-		IBWARN("trap number %d not upported", trapnum);
+		IBWARN("trap number %d not supported", trapnum);
 		return -1;
 	}
 
-	memset(req.mad, 0, sizeof(req.mad));
-	encode_trap_header(req.mad);
-	if (encode_trapfn(port, data) < 0)
+	req = malloc(sizeof(*req) + MAD_BLOCK_SIZE);
+	if (!req) {
+		IBWARN("no mem for trap MAD: %m");
 		return -1;
+	}
+
+	memset(req->mad, 0, MAD_BLOCK_SIZE);
+	encode_trap_header(req->mad);
+	if (encode_trapfn(port, req->mad + 64) < 0) {
+		free(req);
+		return -1;
+	}
 
 	if (!(destport = lid_route_MAD(port, port->smlid))) {
+		free(req);
 		IBWARN("routing failed: no route to dest lid %d", port->smlid);
 		return -1;
 	}
 
-	req.dlid = htons(port->smlid);
-	req.slid = htons(lid);
-	req.sqp = 0;
-	req.dqp = 0;
-	req.status = 0;
-	req.context = 0;
+	req->dlid = htons(port->smlid);
+	req->slid = htons(lid);
+	req->sqp = 0;
+	req->dqp = 0;
+	req->status = 0;
+	req->length = MAD_BLOCK_SIZE;
+	req->context = 0;
 
 	// find SM client
 	cl = find_client(destport, 0, 1, 0);
 
-	if (!cl)
+	if (!cl) {
+		free(req);
 		return 0;
+	}
 
 	if (simverb > 2) {
 		xdump(stdout, "--- packet ---\n", &req, 256);
 		fflush(stdout);
 	}
 
-	ret = write(cl->fd, &req, sizeof(req));
-	if (ret == sizeof(req))
+	ret = write(cl->fd, req, sizeof(*req) + MAD_BLOCK_SIZE);
+	free(req);
+	if (ret == sizeof(*req) + MAD_BLOCK_SIZE)
 		return 0;
 
 	if (ret < 0 && (errno == ECONNREFUSED || errno == ENOTCONN)) {
diff --git a/include/ibsim.h b/include/ibsim.h
index 84568e6..2c6a841 100644
--- a/include/ibsim.h
+++ b/include/ibsim.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006,2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
  *
  * This file is part of ibsim.
  *
@@ -61,14 +62,17 @@ struct sim_port {
 #define SIM_MAGIC	0xdeadbeef
 #define SIM_CTL_MAX_DATA	64
 
+#define MAD_BLOCK_SIZE		256
+
 struct sim_request {
 	uint32_t dlid;
 	uint32_t slid;
 	uint32_t dqp;
 	uint32_t sqp;
 	uint32_t status;
-	uint64_t context;
-	char mad[256];
+	uint32_t length;
+	uint32_t context;
+	char mad[0];
 };
 
 enum SIM_CTL_TYPES {
diff --git a/umad2sim/umad2sim.c b/umad2sim/umad2sim.c
index 4cbf8da..6f0fbad 100644
--- a/umad2sim/umad2sim.c
+++ b/umad2sim/umad2sim.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006,2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
  *
  * This file is part of ibsim.
  *
@@ -376,30 +377,46 @@ static int dev_sysfs_create(struct umad2sim_dev *dev)
 
 static ssize_t umad2sim_read(struct umad2sim_dev *dev, void *buf, size_t count)
 {
-	struct sim_request req;
+	struct sim_request *req;
 	ib_user_mad_t *umad = (ib_user_mad_t *) buf;
 	unsigned mgmt_class;
 	int cnt;
 
 	DEBUG("umad2sim_read: %zu...\n", count);
+	req = malloc(sizeof(*req) + MAD_BLOCK_SIZE);
+	if (!req) {
+		ERROR("umad2sim_read: no mem: %m\n");
+		return 0; /* ???? */
+	}
 
-	cnt = real_read(dev->sim_client.fd_pktin, &req, sizeof(req));
+	cnt = real_read(dev->sim_client.fd_pktin, req,
+			sizeof(*req) + MAD_BLOCK_SIZE);
 	DEBUG("umad2sim_read: got %d...\n", cnt);
-	if (cnt < sizeof(req)) {
-		ERROR("umad2sim_read: partial request - skip.\n");
+	if (cnt < sizeof(*req)) {
+		free(req);
+		ERROR("umad2sim_read: sim header incomplete - skip.\n");
+		umad->status = EAGAIN;
+		return umad_size();
+	}
+
+	if (cnt != sizeof(*req) + req->length) {
+		free(req);
+		ERROR("umad2sim_read: partial request - got %d length "
+		      "in sim header %d - skip.\n",
+		      cnt, sizeof(*req) + req->length);
 		umad->status = EAGAIN;
 		return umad_size();
 	}
 
-	mgmt_class = mad_get_field(req.mad, 0, IB_MAD_MGMTCLASS_F);
+	mgmt_class = mad_get_field(req->mad, 0, IB_MAD_MGMTCLASS_F);
 
 	DEBUG("umad2sim_read: mad: method=%x, response=%x, mgmtclass=%x, "
 	      "attrid=%x, attrmod=%x\n",
-	      mad_get_field(req.mad, 0, IB_MAD_METHOD_F),
-	      mad_get_field(req.mad, 0, IB_MAD_RESPONSE_F),
+	      mad_get_field(req->mad, 0, IB_MAD_METHOD_F),
+	      mad_get_field(req->mad, 0, IB_MAD_RESPONSE_F),
 	      mgmt_class,
-	      mad_get_field(req.mad, 0, IB_MAD_ATTRID_F),
-	      mad_get_field(req.mad, 0, IB_MAD_ATTRMOD_F)
+	      mad_get_field(req->mad, 0, IB_MAD_ATTRID_F),
+	      mad_get_field(req->mad, 0, IB_MAD_ATTRMOD_F)
 	    );
 
 	if (mgmt_class >= arrsize(dev->agent_idx)) {
@@ -407,23 +424,24 @@ static ssize_t umad2sim_read(struct umad2sim_dev *dev, void *buf, size_t count)
 		mgmt_class = 0;
 	}
 
+	cnt -= sizeof(*req);
 	umad->agent_id = dev->agent_idx[mgmt_class];
-	umad->status = ntohl(req.status);
+	umad->status = ntohl(req->status);
 	umad->timeout_ms = 0;
 	umad->retries = 0;
-	umad->length = umad_size() + sizeof(req.mad);
+	umad->length = umad_size() + cnt;
 
-	umad->addr.qpn = req.sqp;
+	umad->addr.qpn = req->sqp;
 	umad->addr.qkey = 0;	// agent->qkey;
-	umad->addr.lid = req.slid;
+	umad->addr.lid = req->slid;
 	umad->addr.sl = 0;	// agent->sl;
 	umad->addr.path_bits = 0;
 	umad->addr.grh_present = 0;
 
-	cnt -= sizeof(req) - sizeof(req.mad);
 	if (cnt > count - umad_size())
 		cnt = count - umad_size();
-	memcpy(umad_get_mad(umad), req.mad, cnt);
+	memcpy(umad_get_mad(umad), req->mad, cnt);
+	free(req);
 
 	return cnt + umad_size();
 }
@@ -431,9 +449,9 @@ static ssize_t umad2sim_read(struct umad2sim_dev *dev, void *buf, size_t count)
 static ssize_t umad2sim_write(struct umad2sim_dev *dev,
 			      const void *buf, size_t count)
 {
-	struct sim_request req;
+	struct sim_request *req;
 	ib_user_mad_t *umad = (ib_user_mad_t *) buf;
-	int cnt;
+	int cnt, ocnt;
 
 #ifdef SIMULATE_SEND_ERRORS
 	{ static int err_count;
@@ -464,25 +482,33 @@ static ssize_t umad2sim_write(struct umad2sim_dev *dev,
 	      mad_get_field(umad_get_mad(umad), 0, IB_MAD_ATTRMOD_F)
 	    );
 
-	req.dlid = umad->addr.lid;
-	req.slid = req.dlid == 0xffff ? 0xffff : 0;	/* 0 - means auto
+	cnt = count - umad_size();
+	if (cnt > MAD_BLOCK_SIZE)
+		cnt = MAD_BLOCK_SIZE;
+	req = malloc(sizeof(*req) + cnt);
+	if (!req) {
+		ERROR("umad2sim_write: no mem for sim req: %m");
+		return -1;
+	}
+
+	req->dlid = umad->addr.lid;
+	req->slid = req->dlid == 0xffff ? 0xffff : 0;	/* 0 - means auto
 							   (supported by ibsim) */ ;
-	req.dqp = umad->addr.qpn;
-	req.sqp = htonl(dev->agents[umad->agent_id].qpn);
-	req.status = 0;
-	req.context = 0;
+	req->dqp = umad->addr.qpn;
+	req->sqp = htonl(dev->agents[umad->agent_id].qpn);
+	req->status = 0;
+	req->length = cnt;
+	req->context = 0;
 
-	cnt = count - umad_size();
-	if (cnt > sizeof(req.mad))
-		cnt = sizeof(req.mad);
-	memcpy(req.mad, umad_get_mad(umad), cnt);
+	memcpy(req->mad, umad_get_mad(umad), cnt);
 
-	cnt = write(dev->sim_client.fd_pktout, (void *)&req, sizeof(req));
-	if (cnt < 0) {
+	ocnt = write(dev->sim_client.fd_pktout, req, sizeof(*req) + cnt);
+	free(req);
+	if (ocnt < 0) {
 		ERROR("umad2sim_write: cannot write\n");
 		return -1;
 	}
-	if (cnt < sizeof(req)) {
+	if (ocnt < sizeof(*req) + cnt) {
 		ERROR("umad2sim_write: partial write\n");
 	}
 





More information about the general mailing list