From caa440caacda09f9559a4543c06eb6c95bb94986 Mon Sep 17 00:00:00 2001 From: Shamir Rabinovitch Date: Sat, 28 Jun 2014 16:25:16 -0700 Subject: [PATCH] rds: new extension header: rdma bytes Introduce a new extension header type RDSV3_EXTHDR_RDMA_BYTES for an RDMA initiator to exchange rdma byte counts to its target. Add new flag to RDS header: RDS_FLAG_EXTHDR_EXTENSION Add new extension to RDS header: rds_ext_header_rdma_bytes Please note: Linux RDS and Solaris RDS have miss match in header flags. Solaris RDS assigned flag 0x08 to RDS_FLAG_EXTHDR_EXTENSION. Linux alredy use 0x08 for flag RDS_FLAG_HB_PING. This patch require the below fix from the Solaris side: BUG 19065367 - unified RDSV3_EXTHDR_RDMA_BYTES with Linux Orabug: 18468180 Signed-off-by: Shamir Rabinovitch Acked-by: Sherman Pun Signed-off-by: Guangyu Sun (cherry picked from commit 5f4f74d028a0d9f8e0391cc6114314e780e65583) --- net/rds/ib_send.c | 17 +++++++++++++++++ net/rds/message.c | 41 +++++++++++++++++++++++++++++++++++++---- net/rds/rds.h | 26 ++++++++++++++++++++------ 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index f7f0c9460208..de826b511e5f 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -591,10 +591,27 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, * used by the peer to release use-once RDMA MRs. */ if (rm->rdma.op_active) { struct rds_ext_header_rdma ext_hdr; + struct rds_ext_header_rdma_bytes rdma_bytes_ext_hdr; ext_hdr.h_rdma_rkey = cpu_to_be32(rm->rdma.op_rkey); rds_message_add_extension(&rm->m_inc.i_hdr, RDS_EXTHDR_RDMA, &ext_hdr, sizeof(ext_hdr)); + + /* prepare the rdma bytes ext header */ + rdma_bytes_ext_hdr.h_rflags = rm->rdma.op_write ? + RDS_FLAG_RDMA_WR_BYTES : RDS_FLAG_RDMA_RD_BYTES; + rdma_bytes_ext_hdr.h_rdma_bytes = + cpu_to_be32(rm->rdma.op_bytes); + + if (rds_message_add_extension(&rm->m_inc.i_hdr, + RDS_EXTHDR_RDMA_BYTES, &rdma_bytes_ext_hdr, + sizeof(rdma_bytes_ext_hdr))) { + /* rdma bytes ext header was added succesfully, + * notify the remote side via flag in header + */ + rm->m_inc.i_hdr.h_flags |= + RDS_FLAG_EXTHDR_EXTENSION; + } } if (rm->m_rdma_cookie) { rds_message_add_rdma_dest_extension(&rm->m_inc.i_hdr, diff --git a/net/rds/message.c b/net/rds/message.c index 277f8e306722..164518d68abd 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -39,6 +39,7 @@ static unsigned int rds_exthdr_size[__RDS_EXTHDR_MAX] = { [RDS_EXTHDR_VERSION] = sizeof(struct rds_ext_header_version), [RDS_EXTHDR_RDMA] = sizeof(struct rds_ext_header_rdma), [RDS_EXTHDR_RDMA_DEST] = sizeof(struct rds_ext_header_rdma_dest), +[RDS_EXTHDR_RDMA_BYTES] = sizeof(struct rds_ext_header_rdma_bytes), }; @@ -101,18 +102,51 @@ void rds_message_populate_header(struct rds_header *hdr, __be16 sport, hdr->h_sport = sport; hdr->h_dport = dport; hdr->h_sequence = cpu_to_be64(seq); - hdr->h_exthdr[0] = RDS_EXTHDR_NONE; + /* see rds_find_next_ext_space for reason why we memset the + * ext header + */ + memset(hdr->h_exthdr, RDS_EXTHDR_NONE, RDS_HEADER_EXT_SPACE); } EXPORT_SYMBOL_GPL(rds_message_populate_header); +/* + * Find the next place we can add rds header extension with specific lenght. + * Extension headers are pushed one after the other as follow: + * [ [ ext #1 ] RDS_EXTHDR_NONE [ ext #2 ] RDS_EXTHDR_NONE ... ] + * Last extension is detected as follow: + * [ [ ext #n ] RDS_EXTHDR_NONE RDS_EXTHDR_NONE ] + * See Orabug: 18468180 - NEW EXTENSION HEADER TYPE RDSV3_EXTHDR_RDMA_BYTES + */ +static int rds_find_next_ext_space(struct rds_header *hdr, unsigned int len, + u8 **ext_start) +{ + int ind; + + for (ind = 0; ind < RDS_HEADER_EXT_SPACE - 1; ind++) { + if (hdr->h_exthdr[ind] != RDS_EXTHDR_NONE || + hdr->h_exthdr[ind + 1] != RDS_EXTHDR_NONE) + continue; + /* found free space in ext header */ + /* skip the RDS_EXTHDR_NONE only if not on first ext */ + if (ind > 0) + ind++; + if (RDS_HEADER_EXT_SPACE - ind < len) + return 1; + /* extension can fit to header */ + *ext_start = hdr->h_exthdr + ind; + return 0; + } + /* no room for extension */ + return 1; +} + int rds_message_add_extension(struct rds_header *hdr, unsigned int type, const void *data, unsigned int len) { unsigned int ext_len = sizeof(u8) + len; unsigned char *dst; - /* For now, refuse to add more than one extension header */ - if (hdr->h_exthdr[0] != RDS_EXTHDR_NONE) + if (rds_find_next_ext_space(hdr, ext_len, &dst)) return 0; if (type >= __RDS_EXTHDR_MAX @@ -121,7 +155,6 @@ int rds_message_add_extension(struct rds_header *hdr, if (ext_len >= RDS_HEADER_EXT_SPACE) return 0; - dst = hdr->h_exthdr; *dst++ = type; memcpy(dst, data, len); diff --git a/net/rds/rds.h b/net/rds/rds.h index 104a0ee06e0f..f02621dd9ea9 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -173,12 +173,13 @@ struct rds_connection { unsigned int c_route_resolved; }; -#define RDS_FLAG_CONG_BITMAP 0x01 -#define RDS_FLAG_ACK_REQUIRED 0x02 -#define RDS_FLAG_RETRANSMITTED 0x04 -#define RDS_FLAG_HB_PING 0x08 -#define RDS_FLAG_HB_PONG 0x10 -#define RDS_MAX_ADV_CREDIT 127 +#define RDS_FLAG_CONG_BITMAP 0x01 +#define RDS_FLAG_ACK_REQUIRED 0x02 +#define RDS_FLAG_RETRANSMITTED 0x04 +#define RDS_FLAG_HB_PING 0x08 +#define RDS_FLAG_HB_PONG 0x10 +#define RDS_FLAG_EXTHDR_EXTENSION 0x20 +#define RDS_MAX_ADV_CREDIT 127 /* * Maximum space available for extension headers. @@ -239,6 +240,19 @@ struct rds_ext_header_rdma_dest { __be32 h_rdma_offset; }; +/* + * This extension header tells the peer about delivered RDMA byte count. + */ +#define RDS_EXTHDR_RDMA_BYTES 4 + +#define RDS_FLAG_RDMA_WR_BYTES 0x01 +#define RDS_FLAG_RDMA_RD_BYTES 0x02 + +struct rds_ext_header_rdma_bytes { + __be32 h_rdma_bytes; /* byte count */ + u8 h_rflags; /* direction of RDMA, write or read */ +}; + #define __RDS_EXTHDR_MAX 16 /* for now */ struct rds_incoming { -- 2.50.1