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 <shamir.rabinovitch@oracle.com>
Acked-by: Sherman Pun <sherman.pun@oracle.com>
Signed-off-by: Guangyu Sun <guangyu.sun@oracle.com>
(cherry picked from commit
5f4f74d028a0d9f8e0391cc6114314e780e65583)
* 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,
[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),
};
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
if (ext_len >= RDS_HEADER_EXT_SPACE)
return 0;
- dst = hdr->h_exthdr;
*dst++ = type;
memcpy(dst, data, len);
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.
__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 {