net/smc: add termination reason and handle LLC protocol violation
Allow to set the reason code for the link group termination, and set meaningful values before termination processing is triggered. This reason code is sent to the peer in the final delete link message. When the LLC request or response layer receives a message type that was not handled, drop a warning and terminate the link group. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ad6c111b8a
commit
3e0c40afce
@ -878,8 +878,11 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
|
|||||||
smc_ism_put_vlan(lgr->smcd, lgr->vlan_id);
|
smc_ism_put_vlan(lgr->smcd, lgr->vlan_id);
|
||||||
put_device(&lgr->smcd->dev);
|
put_device(&lgr->smcd->dev);
|
||||||
} else {
|
} else {
|
||||||
smc_llc_send_link_delete_all(lgr, false,
|
u32 rsn = lgr->llc_termination_rsn;
|
||||||
SMC_LLC_DEL_OP_INIT_TERM);
|
|
||||||
|
if (!rsn)
|
||||||
|
rsn = SMC_LLC_DEL_PROG_INIT_TERM;
|
||||||
|
smc_llc_send_link_delete_all(lgr, false, rsn);
|
||||||
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
|
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
|
||||||
struct smc_link *lnk = &lgr->lnk[i];
|
struct smc_link *lnk = &lgr->lnk[i];
|
||||||
|
|
||||||
@ -1018,6 +1021,7 @@ void smc_smcr_terminate_all(struct smc_ib_device *smcibdev)
|
|||||||
|
|
||||||
list_for_each_entry_safe(lgr, lg, &lgr_free_list, list) {
|
list_for_each_entry_safe(lgr, lg, &lgr_free_list, list) {
|
||||||
list_del_init(&lgr->list);
|
list_del_init(&lgr->list);
|
||||||
|
smc_llc_set_termination_rsn(lgr, SMC_LLC_DEL_OP_INIT_TERM);
|
||||||
__smc_lgr_terminate(lgr, false);
|
__smc_lgr_terminate(lgr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +271,8 @@ struct smc_link_group {
|
|||||||
/* protects llc flow */
|
/* protects llc flow */
|
||||||
int llc_testlink_time;
|
int llc_testlink_time;
|
||||||
/* link keep alive time */
|
/* link keep alive time */
|
||||||
|
u32 llc_termination_rsn;
|
||||||
|
/* rsn code for termination */
|
||||||
};
|
};
|
||||||
struct { /* SMC-D */
|
struct { /* SMC-D */
|
||||||
u64 peer_gid;
|
u64 peer_gid;
|
||||||
|
@ -1420,6 +1420,14 @@ static void smc_llc_rmt_delete_rkey(struct smc_link_group *lgr)
|
|||||||
smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
|
smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void smc_llc_protocol_violation(struct smc_link_group *lgr, u8 type)
|
||||||
|
{
|
||||||
|
pr_warn_ratelimited("smc: SMC-R lg %*phN LLC protocol violation: "
|
||||||
|
"llc_type %d\n", SMC_LGR_ID_SIZE, &lgr->id, type);
|
||||||
|
smc_llc_set_termination_rsn(lgr, SMC_LLC_DEL_PROT_VIOL);
|
||||||
|
smc_lgr_terminate_sched(lgr);
|
||||||
|
}
|
||||||
|
|
||||||
/* flush the llc event queue */
|
/* flush the llc event queue */
|
||||||
static void smc_llc_event_flush(struct smc_link_group *lgr)
|
static void smc_llc_event_flush(struct smc_link_group *lgr)
|
||||||
{
|
{
|
||||||
@ -1520,6 +1528,9 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
|
|||||||
smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
|
smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
default:
|
||||||
|
smc_llc_protocol_violation(lgr, llc->raw.hdr.common.type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
kfree(qentry);
|
kfree(qentry);
|
||||||
@ -1579,6 +1590,9 @@ static void smc_llc_rx_response(struct smc_link *link,
|
|||||||
case SMC_LLC_CONFIRM_RKEY_CONT:
|
case SMC_LLC_CONFIRM_RKEY_CONT:
|
||||||
/* not used because max links is 3 */
|
/* not used because max links is 3 */
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
smc_llc_protocol_violation(link->lgr, llc_type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
kfree(qentry);
|
kfree(qentry);
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,14 @@ static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set the termination reason code for the link group */
|
||||||
|
static inline void smc_llc_set_termination_rsn(struct smc_link_group *lgr,
|
||||||
|
u32 rsn)
|
||||||
|
{
|
||||||
|
if (!lgr->llc_termination_rsn)
|
||||||
|
lgr->llc_termination_rsn = rsn;
|
||||||
|
}
|
||||||
|
|
||||||
/* transmit */
|
/* transmit */
|
||||||
int smc_llc_send_confirm_link(struct smc_link *lnk,
|
int smc_llc_send_confirm_link(struct smc_link *lnk,
|
||||||
enum smc_llc_reqresp reqresp);
|
enum smc_llc_reqresp reqresp);
|
||||||
|
Loading…
Reference in New Issue
Block a user