- int i;
- int down = 0;
- int ptl_up = 0;
- int ptl_down = 0;
- lnet_ping_info_t *info;
-
- if (!avoid_asym_router_failure)
- return -ENOENT;
-
- if (rtr->lp_rcd == NULL)
- return -EINVAL;
-
- if (!rtr->lp_alive)
- return -EINVAL; /* stale lp_rcd */
-
- info = rtr->lp_rcd->rcd_pinginfo;
- LASSERT (info != NULL);
-
- /* NB always racing with network! */
- if (info->pi_magic == __swab32(LNET_PROTO_PING_MAGIC)) {
- lnet_swap_pinginfo(info);
- } else if (info->pi_magic != LNET_PROTO_PING_MAGIC) {
- CNETERR("%s: Unexpected magic %08x\n",
- libcfs_nid2str(rtr->lp_nid), info->pi_magic);
- return -EPROTO;
- }
-
- if (info->pi_version == LNET_PROTO_PING_VERSION1)
- return -ENOENT; /* v1 doesn't carry NI status info */
-
- if (info->pi_version != LNET_PROTO_PING_VERSION) {
- CNETERR("%s: Unexpected version 0x%x\n",
- libcfs_nid2str(rtr->lp_nid), info->pi_version);
- return -EPROTO;
- }
-
- for (i = 0; i < info->pi_nnis && i < LNET_MAX_RTR_NIS; i++) {
- lnet_ni_status_t *stat = &info->pi_ni[i];
- lnet_nid_t nid = stat->ns_nid;
-
- if (nid == LNET_NID_ANY) {
- CNETERR("%s: unexpected LNET_NID_ANY\n",
- libcfs_nid2str(rtr->lp_nid));
- return -EPROTO;
- }
-
- if (LNET_NETTYP(LNET_NIDNET(nid)) == LOLND)
- continue;
-
- if (stat->ns_status == LNET_NI_STATUS_DOWN) {
- if (LNET_NETTYP(LNET_NIDNET(nid)) == PTLLND)
- ptl_down = 1;
- else
- down++;
- continue;
- }
-
- if (stat->ns_status != LNET_NI_STATUS_UP) {
- CNETERR("%s: Unexpected status 0x%x\n",
- libcfs_nid2str(rtr->lp_nid), stat->ns_status);
- return -EPROTO;
- }
-
- /* ignore downed NIs if there's a NI up for dest network */
- if (LNET_NIDNET(nid) == net)
- return 0;
-
- if (LNET_NETTYP(LNET_NIDNET(nid)) == PTLLND)
- ptl_up = 1;
- }
+ lnet_ping_info_t *info = rcd->rcd_pinginfo;
+ struct lnet_peer *gw = rcd->rcd_gateway;
+ lnet_route_t *rtr;
+
+ if (!gw->lp_alive)
+ return;
+
+ if (info->pi_magic == __swab32(LNET_PROTO_PING_MAGIC))
+ lnet_swap_pinginfo(info);
+
+ /* NB always racing with network! */
+ if (info->pi_magic != LNET_PROTO_PING_MAGIC) {
+ CDEBUG(D_NET, "%s: Unexpected magic %08x\n",
+ libcfs_nid2str(gw->lp_nid), info->pi_magic);
+ gw->lp_ping_feats = LNET_PING_FEAT_INVAL;
+ return;
+ }
+
+ gw->lp_ping_feats = info->pi_features;
+ if ((gw->lp_ping_feats & LNET_PING_FEAT_MASK) == 0) {
+ CDEBUG(D_NET, "%s: Unexpected features 0x%x\n",
+ libcfs_nid2str(gw->lp_nid), gw->lp_ping_feats);
+ return; /* nothing I can understand */
+ }
+
+ if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) == 0)
+ return; /* can't carry NI status info */
+
+ cfs_list_for_each_entry(rtr, &gw->lp_routes, lr_gwlist) {
+ int ptl_status = LNET_NI_STATUS_INVALID;
+ int down = 0;
+ int up = 0;
+ int i;
+
+ for (i = 0; i < info->pi_nnis && i < LNET_MAX_RTR_NIS; i++) {
+ lnet_ni_status_t *stat = &info->pi_ni[i];
+ lnet_nid_t nid = stat->ns_nid;
+
+ if (nid == LNET_NID_ANY) {
+ CDEBUG(D_NET, "%s: unexpected LNET_NID_ANY\n",
+ libcfs_nid2str(gw->lp_nid));
+ gw->lp_ping_feats = LNET_PING_FEAT_INVAL;
+ return;
+ }
+
+ if (LNET_NETTYP(LNET_NIDNET(nid)) == LOLND)
+ continue;
+
+ if (stat->ns_status == LNET_NI_STATUS_DOWN) {
+ if (LNET_NETTYP(LNET_NIDNET(nid)) != PTLLND)
+ down++;
+ else if (ptl_status != LNET_NI_STATUS_UP)
+ ptl_status = LNET_NI_STATUS_DOWN;
+ continue;
+ }
+
+ if (stat->ns_status == LNET_NI_STATUS_UP) {
+ if (LNET_NIDNET(nid) == rtr->lr_net) {
+ up = 1;
+ break;
+ }
+ /* ptl NIs are considered down only when
+ * they're all down */
+ if (LNET_NETTYP(LNET_NIDNET(nid)) == PTLLND)
+ ptl_status = LNET_NI_STATUS_UP;
+ continue;
+ }
+
+ CDEBUG(D_NET, "%s: Unexpected status 0x%x\n",
+ libcfs_nid2str(gw->lp_nid), stat->ns_status);
+ gw->lp_ping_feats = LNET_PING_FEAT_INVAL;
+ return;
+ }
+
+ if (up) { /* ignore downed NIs if NI for dest network is up */
+ rtr->lr_downis = 0;
+ continue;
+ }
+ rtr->lr_downis = down + (ptl_status == LNET_NI_STATUS_DOWN);
+ }
+}