+ LASSERT(lpni);
+
+ lnet_peer_ni_decref_locked(lpni);
+
+ peer = lpni->lpni_peer_net->lpn_peer;
+
+ /*
+ * If we found a lpni with the same nid as the NID we're trying to
+ * create, then we're trying to create an already existing lpni
+ * that belongs to a different peer
+ */
+ if (peer->lp_primary_nid != nid)
+ return -EEXIST;
+
+ /*
+ * if we found an lpni that is not a multi-rail, which could occur
+ * if lpni is already created as a non-mr lpni or we just created
+ * it, then make sure you indicate that this lpni is a primary mr
+ * capable peer.
+ *
+ * TODO: update flags if necessary
+ */
+ if (!peer->lp_multi_rail && peer->lp_primary_nid == nid)
+ peer->lp_multi_rail = true;
+
+ return rc;
+}
+
+static int
+lnet_add_peer_ni_to_prim_lpni(lnet_nid_t key_nid, lnet_nid_t nid)
+{
+ struct lnet_peer *peer, *primary_peer;
+ struct lnet_peer_ni *lpni = NULL, *klpni = NULL;
+
+ LASSERT(key_nid != LNET_NID_ANY && nid != LNET_NID_ANY);
+
+ /*
+ * key nid must be created by this point. If not then this
+ * operation is not permitted
+ */
+ klpni = lnet_find_peer_ni_locked(key_nid);
+ if (!klpni)
+ return -ENOENT;
+
+ lnet_peer_ni_decref_locked(klpni);
+
+ primary_peer = klpni->lpni_peer_net->lpn_peer;
+
+ lpni = lnet_find_peer_ni_locked(nid);
+ if (lpni) {
+ lnet_peer_ni_decref_locked(lpni);
+
+ peer = lpni->lpni_peer_net->lpn_peer;
+ /*
+ * lpni already exists in the system but it belongs to
+ * a different peer. We can't re-added it
+ */
+ if (peer->lp_primary_nid != key_nid && peer->lp_multi_rail) {
+ CERROR("Cannot add NID %s owned by peer %s to peer %s\n",
+ libcfs_nid2str(lpni->lpni_nid),
+ libcfs_nid2str(peer->lp_primary_nid),
+ libcfs_nid2str(key_nid));
+ return -EEXIST;
+ } else if (peer->lp_primary_nid == key_nid) {
+ /*
+ * found a peer_ni that is already part of the
+ * peer. This is a no-op operation.
+ */
+ return 0;
+ }
+
+ /*
+ * TODO: else if (peer->lp_primary_nid != key_nid &&
+ * !peer->lp_multi_rail)
+ * peer is not an MR peer and it will be moved in the next
+ * step to klpni, so update its flags accordingly.
+ * lnet_move_peer_ni()
+ */
+
+ /*
+ * TODO: call lnet_update_peer() from here to update the
+ * flags. This is the case when the lpni you're trying to
+ * add is already part of the peer. This could've been
+ * added by the DD previously, so go ahead and do any
+ * updates to the state if necessary
+ */
+
+ }
+
+ /*
+ * When we get here we either have found an existing lpni, which
+ * we can switch to the new peer. Or we need to create one and
+ * add it to the new peer
+ */
+ return lnet_peer_setup_hierarchy(primary_peer, lpni, nid);
+}
+
+/*
+ * lpni creation initiated due to traffic either sending or receiving.
+ */
+static int
+lnet_peer_ni_traffic_add(lnet_nid_t nid)
+{
+ struct lnet_peer_ni *lpni;
+ int rc = 0;
+
+ if (nid == LNET_NID_ANY)
+ return -EINVAL;
+
+ /* lnet_net_lock is not needed here because ln_api_lock is held */
+ lpni = lnet_find_peer_ni_locked(nid);
+ if (lpni) {
+ /*
+ * TODO: lnet_update_primary_nid() but not all of it
+ * only indicate if we're converting this to MR capable
+ * Can happen due to DD
+ */
+ lnet_peer_ni_decref_locked(lpni);
+ } else {
+ rc = lnet_peer_setup_hierarchy(NULL, NULL, nid);
+ }
+
+ return rc;
+
+}
+
+static int
+lnet_peer_ni_add_non_mr(lnet_nid_t nid)
+{
+ struct lnet_peer_ni *lpni;
+
+ lpni = lnet_find_peer_ni_locked(nid);
+ if (lpni) {
+ CERROR("Cannot add %s as non-mr when it already exists\n",
+ libcfs_nid2str(nid));
+ lnet_peer_ni_decref_locked(lpni);
+ return -EEXIST;
+ }
+
+ return lnet_peer_setup_hierarchy(NULL, NULL, nid);
+}