net/smc: respond to test link messages
authorKarsten Graul <kgraul@linux.vnet.ibm.com>
Thu, 1 Mar 2018 12:51:29 +0000 (13:51 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Mar 2018 18:21:31 +0000 (13:21 -0500)
Add TEST LINK message responses, which also serves as preparation for
support of sockopt TCP_KEEPALIVE.

Signed-off-by: Karsten Graul <kgraul@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/smc_llc.c
net/smc/smc_llc.h

index e4502bb..9e0a556 100644 (file)
@@ -41,8 +41,15 @@ struct smc_llc_msg_confirm_link {    /* type 0x01 */
        u8 reserved[9];
 };
 
+struct smc_llc_msg_test_link {         /* type 0x07 */
+       struct smc_llc_hdr hd;
+       u8 user_data[16];
+       u8 reserved[24];
+};
+
 union smc_llc_msg {
        struct smc_llc_msg_confirm_link confirm_link;
+       struct smc_llc_msg_test_link test_link;
        struct {
                struct smc_llc_hdr hdr;
                u8 data[SMC_LLC_DATA_LEN];
@@ -130,6 +137,30 @@ int smc_llc_send_confirm_link(struct smc_link *link, u8 mac[],
        return rc;
 }
 
+/* send LLC test link request or response */
+int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16],
+                          enum smc_llc_reqresp reqresp)
+{
+       struct smc_llc_msg_test_link *testllc;
+       struct smc_wr_tx_pend_priv *pend;
+       struct smc_wr_buf *wr_buf;
+       int rc;
+
+       rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
+       if (rc)
+               return rc;
+       testllc = (struct smc_llc_msg_test_link *)wr_buf;
+       memset(testllc, 0, sizeof(*testllc));
+       testllc->hd.common.type = SMC_LLC_TEST_LINK;
+       testllc->hd.length = sizeof(struct smc_llc_msg_test_link);
+       if (reqresp == SMC_LLC_RESP)
+               testllc->hd.flags |= SMC_LLC_FLAG_RESP;
+       memcpy(testllc->user_data, user_data, sizeof(testllc->user_data));
+       /* send llc message */
+       rc = smc_wr_tx_send(link, pend);
+       return rc;
+}
+
 /********************************* receive ***********************************/
 
 static void smc_llc_rx_confirm_link(struct smc_link *link,
@@ -149,6 +180,16 @@ static void smc_llc_rx_confirm_link(struct smc_link *link,
        }
 }
 
+static void smc_llc_rx_test_link(struct smc_link *link,
+                                struct smc_llc_msg_test_link *llc)
+{
+       if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
+               /* unused as long as we don't send this type of msg */
+       } else {
+               smc_llc_send_test_link(link, llc->user_data, SMC_LLC_RESP);
+       }
+}
+
 static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
 {
        struct smc_link *link = (struct smc_link *)wc->qp->qp_context;
@@ -158,8 +199,15 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
                return; /* short message */
        if (llc->raw.hdr.length != sizeof(*llc))
                return; /* invalid message */
-       if (llc->raw.hdr.common.type == SMC_LLC_CONFIRM_LINK)
+
+       switch (llc->raw.hdr.common.type) {
+       case SMC_LLC_TEST_LINK:
+               smc_llc_rx_test_link(link, &llc->test_link);
+               break;
+       case SMC_LLC_CONFIRM_LINK:
                smc_llc_rx_confirm_link(link, &llc->confirm_link);
+               break;
+       }
 }
 
 /***************************** init, exit, misc ******************************/
@@ -170,6 +218,10 @@ static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
                .type           = SMC_LLC_CONFIRM_LINK
        },
        {
+               .handler        = smc_llc_rx_handler,
+               .type           = SMC_LLC_TEST_LINK
+       },
+       {
                .handler        = NULL,
        }
 };
index a788860..6c8a062 100644 (file)
@@ -26,11 +26,14 @@ enum smc_llc_reqresp {
 
 enum smc_llc_msg_type {
        SMC_LLC_CONFIRM_LINK            = 0x01,
+       SMC_LLC_TEST_LINK               = 0x07,
 };
 
 /* transmit */
 int smc_llc_send_confirm_link(struct smc_link *lnk, u8 mac[], union ib_gid *gid,
                              enum smc_llc_reqresp reqresp);
+int smc_llc_send_test_link(struct smc_link *lnk, u8 user_data[16],
+                          enum smc_llc_reqresp reqresp);
 int smc_llc_init(void) __init;
 
 #endif /* SMC_LLC_H */