agent: Add IB ping server agent (used with ibping diagnostic tool)

Signed-off-by: Shahar Frank <[EMAIL PROTECTED]>
Signed-off-by: Hal Rosenstock <[EMAIL PROTECTED]>

Index: include/ib_mad.h
===================================================================
--- include/ib_mad.h    (revision 2012)
+++ include/ib_mad.h    (working copy)
@@ -56,6 +56,10 @@
 #define IB_MGMT_CLASS_VENDOR_RANGE2_START      0x30
 #define IB_MGMT_CLASS_VENDOR_RANGE2_END                0x4F
 
+#define IB_MGMT_CLASS_OPENIB_PING      (IB_MGMT_CLASS_VENDOR_RANGE2_START+2)
+
+#define        IB_OPENIB_OUI                           (0x001405)
+
 /* Management methods */
 #define IB_MGMT_METHOD_GET                     0x01
 #define IB_MGMT_METHOD_SET                     0x02
Index: core/agent_priv.h
===================================================================
--- core/agent_priv.h   (revision 2012)
+++ core/agent_priv.h   (working copy)
@@ -57,6 +57,7 @@
        int port_num;
        struct ib_mad_agent *smp_agent;       /* SM class */
        struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
+       struct ib_mad_agent *pingd_agent;     /* OpenIB Ping class */
 };
 
 #endif /* __IB_AGENT_PRIV_H__ */
Index: core/agent.c
===================================================================
--- core/agent.c        (revision 2012)
+++ core/agent.c        (working copy)
@@ -37,7 +37,7 @@
  */
 
 #include <linux/dma-mapping.h>
-
+#include <linux/utsname.h>
 #include <asm/bug.h>
 
 #include <ib_smi.h>
@@ -70,7 +70,8 @@
        } else {
                list_for_each_entry(entry, &ib_agent_port_list, port_list) {
                        if ((entry->smp_agent == mad_agent) ||
-                           (entry->perf_mgmt_agent == mad_agent))
+                           (entry->perf_mgmt_agent == mad_agent) ||
+                           (entry->pingd_agent == mad_agent))
                                return entry;
                }
        }
@@ -151,7 +152,8 @@
        ah_attr.sl = wc->sl;
        ah_attr.static_rate = 0;
        ah_attr.ah_flags = 0; /* No GRH */
-       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
+       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
+           mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_OPENIB_PING) {
                if (wc->wc_flags & IB_WC_GRH) {
                        ah_attr.ah_flags = IB_AH_GRH;
                        /* Should sgid be looked up ? */
@@ -175,7 +177,8 @@
        }
 
        send_wr.wr.ud.ah = agent_send_wr->ah;
-       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
+       if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
+           mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_OPENIB_PING) {
                send_wr.wr.ud.pkey_index = wc->pkey_index;
                send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;
        } else {        /* for SMPs */
@@ -233,6 +236,9 @@
                case IB_MGMT_CLASS_PERF_MGMT:
                        mad_agent = port_priv->perf_mgmt_agent;
                        break;
+               case IB_MGMT_CLASS_OPENIB_PING:
+                       mad_agent = port_priv->pingd_agent;
+                       break;
                default:
                        return 1;
        }
@@ -240,6 +246,42 @@
        return agent_mad_send(mad_agent, port_priv, mad, grh, wc);
 }
 
+static void pingd_recv_handler(struct ib_mad_agent *mad_agent,
+                              struct ib_mad_recv_wc *mad_recv_wc)
+{
+       struct ib_agent_port_private    *port_priv;
+       struct ib_vendor_mad    *vend;
+       struct ib_mad_private *recv = container_of(mad_recv_wc,
+                                       struct ib_mad_private,
+                                       header.recv_wc);
+
+       /* Find matching MAD agent */
+       port_priv = ib_get_agent_port(NULL, 0, mad_agent);
+       if (!port_priv) {
+               kmem_cache_free(ib_mad_cache, recv);
+               printk(KERN_ERR SPFX "pingd_recv_handler: no matching MAD "
+                      "agent %p\n", mad_agent);
+               return;
+       }
+
+       vend = (struct ib_vendor_mad *)mad_recv_wc->recv_buf.mad;
+
+       vend->mad_hdr.method |= IB_MGMT_METHOD_RESP;
+       vend->mad_hdr.status = 0;
+       if (!system_utsname.domainname[0])
+               strncpy(vend->data, system_utsname.nodename, sizeof vend->data);
+       else
+               snprintf(vend->data, sizeof vend->data, "%s.%s",
+                       system_utsname.nodename, system_utsname.domainname);
+
+       /* Send response */
+       if (agent_mad_send(mad_agent, port_priv, recv,
+                          mad_recv_wc->recv_buf.grh, mad_recv_wc->wc)) {
+               kmem_cache_free(ib_mad_cache, recv);
+               printk(KERN_ERR SPFX "pingd_recv_handler: reply failed\n");
+       }
+}
+
 static void agent_send_handler(struct ib_mad_agent *mad_agent,
                               struct ib_mad_send_wc *mad_send_wc)
 {
@@ -278,6 +320,7 @@
 {
        int ret;
        struct ib_agent_port_private *port_priv;
+       struct ib_mad_reg_req pingd_reg_req;
        unsigned long flags;
 
        /* First, check if port already open for SMI */
@@ -324,12 +367,33 @@
                goto error3;
        }
 
+       pingd_reg_req.mgmt_class = IB_MGMT_CLASS_OPENIB_PING;
+       pingd_reg_req.mgmt_class_version = 1;
+       pingd_reg_req.oui[0] = (IB_OPENIB_OUI >> 16) & 0xff;
+       pingd_reg_req.oui[1] = (IB_OPENIB_OUI >> 8) & 0xff;
+       pingd_reg_req.oui[2] = IB_OPENIB_OUI & 0xff;
+       set_bit(IB_MGMT_METHOD_GET, pingd_reg_req.method_mask);
+
+       /* Obtain server MAD agent for OpenIB Ping class (GSI QP) */
+       port_priv->pingd_agent = ib_register_mad_agent(device, port_num,
+                                                      IB_QPT_GSI,
+                                                     &pingd_reg_req, 0,
+                                                     &agent_send_handler,
+                                                     &pingd_recv_handler,
+                                                      NULL);
+       if (IS_ERR(port_priv->pingd_agent)) {
+               ret = PTR_ERR(port_priv->pingd_agent);
+               goto error4;
+       }
+
        spin_lock_irqsave(&ib_agent_port_list_lock, flags);
        list_add_tail(&port_priv->port_list, &ib_agent_port_list);
        spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
        return 0;
 
+error4:
+       ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
 error3:
        ib_unregister_mad_agent(port_priv->smp_agent);
 error2:
@@ -353,6 +417,7 @@
        list_del(&port_priv->port_list);
        spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
+       ib_unregister_mad_agent(port_priv->pingd_agent);
        ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
        ib_unregister_mad_agent(port_priv->smp_agent);
        kfree(port_priv);



_______________________________________________
openib-general mailing list
openib-general@openib.org
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to