Commit fd5b4070 authored by Yizhen Fan's avatar Yizhen Fan Committed by fanyizhen1995
Browse files

ub: ubcore add handle restore tp req



driver inclusion
category: feature
bugzilla: NA
CVE: NA

--------------------------------

Ubcore add handle restore tp req, which allows ubcore to handle request of
tp restore.

The TP link restore process varies according to the transport
mode and transaction type.

Signed-off-by: default avatarGuoxin Qian <qianguoxin@huawei.com>
Signed-off-by: default avatarYizhen Fan <fanyizhen@huawei.com>
parent ee7e814e
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -113,6 +113,19 @@ struct ubcore_nl_query_tp_resp {
	struct ubcore_multipath_tp_cfg cfg;
};

struct ubcore_nl_restore_tp_req {
	enum ubcore_transport_mode trans_mode;
	uint32_t tpn;
	uint32_t peer_tpn;
	uint32_t rx_psn;
	struct ubcore_ta_data ta;
};

struct ubcore_nl_restore_tp_resp {
	enum ubcore_nl_resp_status ret;
	uint32_t peer_rx_psn;
};

struct ubcore_nl_session {
	struct ubcore_nlmsg *req;
	struct ubcore_nlmsg *resp;
+138 −0
Original line number Diff line number Diff line
@@ -930,3 +930,141 @@ int ubcore_advise_tp(struct ubcore_device *dev, const union ubcore_eid *remote_e
	return 0;
}
EXPORT_SYMBOL(ubcore_advise_tp);

static struct ubcore_nlmsg *ubcore_get_restore_tp_response(struct ubcore_nlmsg *req,
							   struct ubcore_tp *tp)
{
	struct ubcore_nl_restore_tp_resp *restore_resp;
	struct ubcore_nlmsg *resp = NULL;

	resp = ubcore_alloc_nlmsg(sizeof(struct ubcore_nl_restore_tp_resp), &req->dst_eid,
				  &req->src_eid);
	if (resp == NULL) {
		ubcore_log_err("Failed to alloc restore tp response");
		return NULL;
	}

	resp->msg_type = UBCORE_NL_RESTORE_TP_RESP;
	resp->nlmsg_seq = req->nlmsg_seq;
	resp->transport_type = req->transport_type;
	restore_resp = (struct ubcore_nl_restore_tp_resp *)resp->payload;

	if (tp == NULL) {
		restore_resp->ret = UBCORE_NL_RESP_FAIL;
		return resp;
	}

	restore_resp->peer_rx_psn = tp->rx_psn;
	return resp;
}

static int ubcore_restore_tp_to_rts(const struct ubcore_device *dev, struct ubcore_tp *tp,
				    uint32_t rx_psn, uint32_t tx_psn)
{
	union ubcore_tp_attr_mask mask;
	struct ubcore_tp_attr attr;

	mask.value = 0;
	mask.bs.state = 1;
	mask.bs.rx_psn = 1;
	mask.bs.tx_psn = 1;

	attr.state = UBCORE_TP_STATE_RTS;
	attr.rx_psn = rx_psn;
	attr.tx_psn = tx_psn;

	if (dev->ops->modify_tp(tp, &attr, mask) != 0) {
		/* tp->peer_ext.addr will be freed when called ubcore_destroy_tp */
		ubcore_log_err("Failed to modify tp");
		return -1;
	}

	tp->state = UBCORE_TP_STATE_RTS;
	tp->rx_psn = rx_psn;
	tp->tx_psn = tx_psn;

	return 0;
}

/* restore target RM tp created by ubcore_advise_target_tp */
static struct ubcore_tp *ubcore_restore_advised_target_tp(struct ubcore_device *dev,
							  struct ubcore_nl_restore_tp_req *restore)
{
	struct ubcore_tp_advice advice;
	struct ubcore_tp_node *tp_node;
	struct ubcore_tp_meta *meta;
	struct ubcore_tp *tp;

	meta = &advice.meta;
	if (ubcore_parse_ta(dev, &restore->ta, &advice) != 0) {
		ubcore_log_err("Failed to parse ta with type %u", restore->ta.type);
		return NULL;
	} else if (meta->ht == NULL) {
		ubcore_log_err("tp table is already released");
		return NULL;
	}

	tp_node = ubcore_hash_table_lookup(meta->ht, meta->hash, &meta->key);
	/* pair with get_tptable in parse_ta */
	ubcore_put_tptable(meta->ht);
	if (tp_node == NULL) {
		ubcore_log_err("tp is not found%u", restore->peer_tpn);
		return NULL;
	}

	tp = tp_node->tp;
	if (ubcore_restore_tp_to_rts(dev, tp, get_random_u32(), restore->rx_psn) != 0) {
		ubcore_log_err("Failed to modify tp to rts %u", restore->rx_psn);
		return NULL;
	}
	return tp;
}

static struct ubcore_tp *ubcore_restore_bound_target_tp(struct ubcore_device *dev,
							struct ubcore_nl_restore_tp_req *restore)
{
	return ubcore_restore_advised_target_tp(dev, restore);
}

static struct ubcore_tp *ubcore_handle_restore_tp(struct ubcore_device *dev,
						  struct ubcore_nl_restore_tp_req *restore)
{
	if (dev->transport_type != UBCORE_TRANSPORT_IB || restore->trans_mode == UBCORE_TP_UM ||
	    restore->ta.type == UBCORE_TA_NONE || restore->ta.type >= UBCORE_TA_VIRT)
		return NULL;

	if (restore->trans_mode == UBCORE_TP_RM)
		return ubcore_restore_advised_target_tp(dev, restore);
	else
		return ubcore_restore_bound_target_tp(dev, restore);
}

struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req)
{
	struct ubcore_nl_restore_tp_req *restore =
		(struct ubcore_nl_restore_tp_req *)(void *)req->payload;
	struct ubcore_device *dev;
	struct ubcore_tp *tp;

	if (req->payload_len != sizeof(struct ubcore_nl_restore_tp_req)) {
		ubcore_log_err("Invalid restore req");
		return NULL;
	}

	dev = ubcore_find_device(&req->dst_eid, req->transport_type);
	if (dev == NULL || !ubcore_have_tp_ops(dev)) {
		if (dev != NULL)
			ubcore_put_device(dev);
		ubcore_log_err("Failed to find device or device ops invalid");
		return ubcore_get_restore_tp_response(req, NULL);
	}

	tp = ubcore_handle_restore_tp(dev, restore);
	if (tp == NULL)
		ubcore_log_err("Failed to restore target tp towards remote eid %pI6c",
			       &req->src_eid);

	ubcore_put_device(dev);
	return ubcore_get_restore_tp_response(req, tp);
}
EXPORT_SYMBOL(ubcore_handle_restore_tp_req);
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ int ubcore_advise_tp(struct ubcore_device *dev, const union ubcore_eid *remote_e

struct ubcore_nlmsg *ubcore_handle_create_tp_req(struct ubcore_nlmsg *req);
struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req);
struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req);

/* Called when clear tp table */
int ubcore_destroy_tp(struct ubcore_tp *tp);
#endif