From 7b31ef0bbac99bfd0f681fb9256f82db8bc9b20d Mon Sep 17 00:00:00 2001 From: Mr NeilBrown Date: Tue, 28 Apr 2020 14:57:09 +1000 Subject: [PATCH] LU-10391 socklnd: add hello message version 4 KSOCK_PROTO_V4 uses a 'hello' message that contains lnet_hdr_nid16 with 16 byte addresses Test-Parameters: trivial Test-Parameters: serverversion=2.12 serverdistro=el7.9 testlist=runtests Test-Parameters: clientversion=2.12 testlist=runtests Signed-off-by: Mr NeilBrown Change-Id: I52a36739d3a84dc059537059a586ce3dab2b20f0 Reviewed-on: https://review.whamcloud.com/43611 Reviewed-by: James Simmons Reviewed-by: Serguei Smirnov Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lnet/include/lnet/lib-lnet.h | 26 +++++ lnet/include/lnet/socklnd.h | 5 + lnet/include/uapi/linux/lnet/lnet-types.h | 4 + lnet/klnds/socklnd/socklnd.h | 1 + lnet/klnds/socklnd/socklnd_cb.c | 8 +- lnet/klnds/socklnd/socklnd_proto.c | 159 +++++++++++++++++++++++++++++- 6 files changed, 195 insertions(+), 8 deletions(-) diff --git a/lnet/include/lnet/lib-lnet.h b/lnet/include/lnet/lib-lnet.h index e4658a8..7d11672 100644 --- a/lnet/include/lnet/lib-lnet.h +++ b/lnet/include/lnet/lib-lnet.h @@ -547,6 +547,32 @@ static inline void lnet_hdr_to_nid4(const struct lnet_hdr *hdr, hdr_nid4->msg = hdr->msg; } +static inline void lnet_hdr_from_nid16(struct lnet_hdr *hdr, + const struct lnet_hdr_nid16 *vhdr) +{ + const struct lnet_hdr *hdr16 = (void *)vhdr; + + hdr->dest_nid = hdr16->dest_nid; + hdr->src_nid = hdr16->src_nid; + hdr->dest_pid = le32_to_cpu(hdr16->dest_pid); + hdr->src_pid = le32_to_cpu(hdr16->src_pid); + hdr->type = le32_to_cpu(hdr16->type); + hdr->payload_length = le32_to_cpu(hdr16->payload_length); +} + +static inline void lnet_hdr_to_nid16(const struct lnet_hdr *hdr, + struct lnet_hdr_nid16 *vhdr) +{ + struct lnet_hdr *hdr16 = (void *)vhdr; + + hdr16->dest_nid = hdr->dest_nid; + hdr16->src_nid = hdr->src_nid; + hdr16->dest_pid = cpu_to_le32(hdr->dest_pid); + hdr16->src_pid = cpu_to_le32(hdr->src_pid); + hdr16->type = cpu_to_le32(hdr->type); + hdr16->payload_length = cpu_to_le32(hdr->payload_length); +} + extern const struct lnet_lnd the_lolnd; extern int avoid_asym_router_failure; diff --git a/lnet/include/lnet/socklnd.h b/lnet/include/lnet/socklnd.h index 22e60ed..ff1fe23 100644 --- a/lnet/include/lnet/socklnd.h +++ b/lnet/include/lnet/socklnd.h @@ -80,6 +80,10 @@ struct ksock_msg { /* - nothing */ /* case ksm_kh.ksh_type == KSOCK_MSG_LNET */ struct lnet_hdr_nid4 lnetmsg_nid4; + /* case ksm_kh.ksh_type == KSOCK_MSG_LNET && + * kshm_version >= KSOCK_PROTO_V4 + */ + struct lnet_hdr_nid16 lnetmsg_nid16; } __packed ksm_u; } __packed; #define ksm_type ksm_kh.ksh_type @@ -90,5 +94,6 @@ struct ksock_msg { * other LND (usocklnd, for example) */ #define KSOCK_PROTO_V2 2 #define KSOCK_PROTO_V3 3 +#define KSOCK_PROTO_V4 4 #endif diff --git a/lnet/include/uapi/linux/lnet/lnet-types.h b/lnet/include/uapi/linux/lnet/lnet-types.h index 02f1bb6..ff02f24 100644 --- a/lnet/include/uapi/linux/lnet/lnet-types.h +++ b/lnet/include/uapi/linux/lnet/lnet-types.h @@ -307,6 +307,10 @@ enum lnet_ins_pos { /** \addtogroup lnet_md * @{ */ +struct lnet_hdr_nid16 { + char _bytes[sizeof(struct lnet_hdr)]; +} __attribute__((packed)); + /** * Event queue handler function type. * diff --git a/lnet/klnds/socklnd/socklnd.h b/lnet/klnds/socklnd/socklnd.h index 7ce64a4..81db1c3 100644 --- a/lnet/klnds/socklnd/socklnd.h +++ b/lnet/klnds/socklnd/socklnd.h @@ -450,6 +450,7 @@ struct ksock_proto { extern const struct ksock_proto ksocknal_protocol_v1x; extern const struct ksock_proto ksocknal_protocol_v2x; extern const struct ksock_proto ksocknal_protocol_v3x; +extern const struct ksock_proto ksocknal_protocol_v4x; #define KSOCK_PROTO_V1_MAJOR LNET_PROTO_TCP_VERSION_MAJOR #define KSOCK_PROTO_V1_MINOR LNET_PROTO_TCP_VERSION_MINOR diff --git a/lnet/klnds/socklnd/socklnd_cb.c b/lnet/klnds/socklnd/socklnd_cb.c index fe3e6cb..2f7fc2a 100644 --- a/lnet/klnds/socklnd/socklnd_cb.c +++ b/lnet/klnds/socklnd/socklnd_cb.c @@ -2046,7 +2046,8 @@ ksocknal_connect(struct ksock_conn_cb *conn_cb) conn = list_first_entry_or_null(&peer_ni->ksnp_conns, struct ksock_conn, ksnc_list); if (conn) - LASSERT(conn->ksnc_proto == &ksocknal_protocol_v3x); + LASSERT(conn->ksnc_proto == &ksocknal_protocol_v3x || + conn->ksnc_proto == &ksocknal_protocol_v4x); /* take all the blocked packets while I've got the lock and * complete below... @@ -2411,8 +2412,9 @@ __must_hold(&ksocknal_data.ksnd_global_lock) if (list_empty(&peer_ni->ksnp_conns)) return 0; - if (peer_ni->ksnp_proto != &ksocknal_protocol_v3x) - return 0; + if (peer_ni->ksnp_proto != &ksocknal_protocol_v3x && + peer_ni->ksnp_proto != &ksocknal_protocol_v4x) + return 0; if (*ksocknal_tunables.ksnd_keepalive <= 0 || ktime_get_seconds() < peer_ni->ksnp_last_alive + diff --git a/lnet/klnds/socklnd/socklnd_proto.c b/lnet/klnds/socklnd/socklnd_proto.c index 789c4d5..40a1ffb 100644 --- a/lnet/klnds/socklnd/socklnd_proto.c +++ b/lnet/klnds/socklnd/socklnd_proto.c @@ -361,6 +361,51 @@ ksocknal_match_tx_v3(struct ksock_conn *conn, struct ksock_tx *tx, int nonblk) } } +static int +ksocknal_match_tx_v4(struct ksock_conn *conn, struct ksock_tx *tx, int nonblk) +{ + int nob; + + if (!tx || !tx->tx_lnetmsg) + nob = sizeof(struct ksock_msg_hdr); + else + nob = sizeof(struct ksock_msg_hdr) + + sizeof(struct lnet_hdr_nid16) + + tx->tx_lnetmsg->msg_len; + + switch (conn->ksnc_type) { + default: + CERROR("ksnc_type bad: %u\n", conn->ksnc_type); + LBUG(); + case SOCKLND_CONN_ANY: + return SOCKNAL_MATCH_NO; + + case SOCKLND_CONN_ACK: + if (nonblk) + return SOCKNAL_MATCH_YES; + else if (tx == NULL || tx->tx_lnetmsg == NULL) + return SOCKNAL_MATCH_MAY; + else + return SOCKNAL_MATCH_NO; + + case SOCKLND_CONN_BULK_OUT: + if (nonblk) + return SOCKNAL_MATCH_NO; + else if (nob < *ksocknal_tunables.ksnd_min_bulk) + return SOCKNAL_MATCH_MAY; + else + return SOCKNAL_MATCH_YES; + + case SOCKLND_CONN_CONTROL: + if (nonblk) + return SOCKNAL_MATCH_NO; + else if (nob >= *ksocknal_tunables.ksnd_min_bulk) + return SOCKNAL_MATCH_MAY; + else + return SOCKNAL_MATCH_YES; + } +} + /* (Sink) handle incoming ZC request from sender */ static int ksocknal_handle_zcreq(struct ksock_conn *c, __u64 cookie, int remote) @@ -420,11 +465,12 @@ ksocknal_handle_zcack(struct ksock_conn *conn, __u64 cookie1, __u64 cookie2) count = (cookie1 > cookie2) ? 2 : (cookie2 - cookie1 + 1); - if (cookie2 == SOCKNAL_KEEPALIVE_PING && - conn->ksnc_proto == &ksocknal_protocol_v3x) { - /* keepalive PING for V3.x, just ignore it */ - return count == 1 ? 0 : -EPROTO; - } + if (cookie2 == SOCKNAL_KEEPALIVE_PING && + (conn->ksnc_proto == &ksocknal_protocol_v3x || + conn->ksnc_proto == &ksocknal_protocol_v4x)) { + /* keepalive PING for V3.x, just ignore it */ + return count == 1 ? 0 : -EPROTO; + } spin_lock(&peer_ni->ksnp_lock); @@ -590,6 +636,24 @@ ksocknal_send_hello_v2(struct ksock_conn *conn, struct ksock_hello_msg *hello) } static int +ksocknal_send_hello_v4(struct ksock_conn *conn, struct ksock_hello_msg *hello) +{ + struct socket *sock = conn->ksnc_sock; + int rc; + + hello->kshm_magic = LNET_PROTO_MAGIC; + hello->kshm_version = conn->ksnc_proto->pro_version; + + rc = lnet_sock_write(sock, hello, sizeof(*hello), + lnet_acceptor_timeout()); + + if (rc != 0) + CNETERR("Error %d sending HELLO hdr to %pISp\n", + rc, &conn->ksnc_peeraddr); + return rc; +} + +static int ksocknal_recv_hello_v1(struct ksock_conn *conn, struct ksock_hello_msg *hello, int timeout) { @@ -744,6 +808,40 @@ ksocknal_recv_hello_v2(struct ksock_conn *conn, struct ksock_hello_msg *hello, return 0; } +static int +ksocknal_recv_hello_v4(struct ksock_conn *conn, struct ksock_hello_msg *hello, + int timeout) +{ + struct socket *sock = conn->ksnc_sock; + int rc; + + if (hello->kshm_magic == LNET_PROTO_MAGIC) + conn->ksnc_flip = 0; + else + conn->ksnc_flip = 1; + + rc = lnet_sock_read(sock, &hello->kshm_src_nid, + sizeof(*hello) - + offsetof(struct ksock_hello_msg, kshm_src_nid), + timeout); + if (rc) { + CERROR("Error %d reading HELLO from %pIS\n", + rc, &conn->ksnc_peeraddr); + LASSERT(rc < 0 && rc != -EALREADY); + return rc; + } + + if (conn->ksnc_flip) { + __swab32s(&hello->kshm_src_pid); + __swab32s(&hello->kshm_dst_pid); + __swab64s(&hello->kshm_src_incarnation); + __swab64s(&hello->kshm_dst_incarnation); + __swab32s(&hello->kshm_ctype); + } + + return 0; +} + static void ksocknal_pack_msg_v1(struct ksock_tx *tx) { @@ -794,6 +892,39 @@ ksocknal_pack_msg_v2(struct ksock_tx *tx) } static void +ksocknal_pack_msg_v4(struct ksock_tx *tx) +{ + int hdr_size; + + tx->tx_hdr.iov_base = (void *)&tx->tx_msg; + + switch (tx->tx_msg.ksm_type) { + case KSOCK_MSG_LNET: + LASSERT(tx->tx_lnetmsg != NULL); + hdr_size = (sizeof(struct ksock_msg_hdr) + + sizeof(struct lnet_hdr_nid16)); + + lnet_hdr_to_nid16(&tx->tx_lnetmsg->msg_hdr, + &tx->tx_msg.ksm_u.lnetmsg_nid16); + tx->tx_hdr.iov_len = hdr_size; + tx->tx_resid = tx->tx_nob = hdr_size + tx->tx_lnetmsg->msg_len; + break; + case KSOCK_MSG_NOOP: + LASSERT(tx->tx_lnetmsg == NULL); + hdr_size = sizeof(struct ksock_msg_hdr); + + tx->tx_hdr.iov_len = hdr_size; + tx->tx_resid = tx->tx_nob = hdr_size; + break; + default: + LASSERT(0); + } + /* Don't checksum before start sending, because packet can be + * piggybacked with ACK + */ +} + +static void ksocknal_unpack_msg_v1(struct ksock_msg *msg, struct lnet_hdr *hdr) { msg->ksm_csum = 0; @@ -808,6 +939,12 @@ ksocknal_unpack_msg_v2(struct ksock_msg *msg, struct lnet_hdr *hdr) lnet_hdr_from_nid4(hdr, &msg->ksm_u.lnetmsg_nid4); } +static void +ksocknal_unpack_msg_v4(struct ksock_msg *msg, struct lnet_hdr *hdr) +{ + lnet_hdr_from_nid16(hdr, &msg->ksm_u.lnetmsg_nid16); +} + const struct ksock_proto ksocknal_protocol_v1x = { .pro_version = KSOCK_PROTO_V1, @@ -850,3 +987,15 @@ const struct ksock_proto ksocknal_protocol_v3x = .pro_match_tx = ksocknal_match_tx_v3 }; +const struct ksock_proto ksocknal_protocol_v4x = { + .pro_version = KSOCK_PROTO_V4, + .pro_send_hello = ksocknal_send_hello_v4, + .pro_recv_hello = ksocknal_recv_hello_v4, + .pro_pack = ksocknal_pack_msg_v4, + .pro_unpack = ksocknal_unpack_msg_v4, + .pro_queue_tx_msg = ksocknal_queue_tx_msg_v2, + .pro_queue_tx_zcack = ksocknal_queue_tx_zcack_v3, + .pro_handle_zcreq = ksocknal_handle_zcreq, + .pro_handle_zcack = ksocknal_handle_zcack, + .pro_match_tx = ksocknal_match_tx_v4, +}; -- 1.8.3.1