⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_sideeffect.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
bail:	return error;}/******************************************************************** * 2nd Level Abstractions ********************************************************************//* This is the side-effect interpreter.  */static int sctp_cmd_interpreter(sctp_event_t event_type,				sctp_subtype_t subtype,				sctp_state_t state,				struct sctp_endpoint *ep,				struct sctp_association *asoc,				void *event_arg,				sctp_disposition_t status,				sctp_cmd_seq_t *commands,				gfp_t gfp){	int error = 0;	int force;	sctp_cmd_t *cmd;	struct sctp_chunk *new_obj;	struct sctp_chunk *chunk = NULL;	struct sctp_packet *packet;	struct list_head *pos;	struct timer_list *timer;	unsigned long timeout;	struct sctp_transport *t;	struct sctp_sackhdr sackh;	int local_cork = 0;	if (SCTP_EVENT_T_TIMEOUT != event_type)		chunk = (struct sctp_chunk *) event_arg;	/* Note:  This whole file is a huge candidate for rework.	 * For example, each command could either have its own handler, so	 * the loop would look like:	 *     while (cmds)	 *         cmd->handle(x, y, z)	 * --jgrimm	 */	while (NULL != (cmd = sctp_next_cmd(commands))) {		switch (cmd->verb) {		case SCTP_CMD_NOP:			/* Do nothing. */			break;		case SCTP_CMD_NEW_ASOC:			/* Register a new association.  */			if (local_cork) {				sctp_outq_uncork(&asoc->outqueue);				local_cork = 0;			}			asoc = cmd->obj.ptr;			/* Register with the endpoint.  */			sctp_endpoint_add_asoc(ep, asoc);			sctp_hash_established(asoc);			break;		case SCTP_CMD_UPDATE_ASSOC:		       sctp_assoc_update(asoc, cmd->obj.ptr);		       break;		case SCTP_CMD_PURGE_OUTQUEUE:		       sctp_outq_teardown(&asoc->outqueue);		       break;		case SCTP_CMD_DELETE_TCB:			if (local_cork) {				sctp_outq_uncork(&asoc->outqueue);				local_cork = 0;			}			/* Delete the current association.  */			sctp_cmd_delete_tcb(commands, asoc);			asoc = NULL;			break;		case SCTP_CMD_NEW_STATE:			/* Enter a new state.  */			sctp_cmd_new_state(commands, asoc, cmd->obj.state);			break;		case SCTP_CMD_REPORT_TSN:			/* Record the arrival of a TSN.  */			sctp_tsnmap_mark(&asoc->peer.tsn_map, cmd->obj.u32);			break;		case SCTP_CMD_REPORT_FWDTSN:			/* Move the Cumulattive TSN Ack ahead. */			sctp_tsnmap_skip(&asoc->peer.tsn_map, cmd->obj.u32);			/* purge the fragmentation queue */			sctp_ulpq_reasm_flushtsn(&asoc->ulpq, cmd->obj.u32);			/* Abort any in progress partial delivery. */			sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);			break;		case SCTP_CMD_PROCESS_FWDTSN:			sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr);			break;		case SCTP_CMD_GEN_SACK:			/* Generate a Selective ACK.			 * The argument tells us whether to just count			 * the packet and MAYBE generate a SACK, or			 * force a SACK out.			 */			force = cmd->obj.i32;			error = sctp_gen_sack(asoc, force, commands);			break;		case SCTP_CMD_PROCESS_SACK:			/* Process an inbound SACK.  */			error = sctp_cmd_process_sack(commands, asoc,						      cmd->obj.ptr);			break;		case SCTP_CMD_GEN_INIT_ACK:			/* Generate an INIT ACK chunk.  */			new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC,						     0);			if (!new_obj)				goto nomem;			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,					SCTP_CHUNK(new_obj));			break;		case SCTP_CMD_PEER_INIT:			/* Process a unified INIT from the peer.			 * Note: Only used during INIT-ACK processing.  If			 * there is an error just return to the outter			 * layer which will bail.			 */			error = sctp_cmd_process_init(commands, asoc, chunk,						      cmd->obj.ptr, gfp);			break;		case SCTP_CMD_GEN_COOKIE_ECHO:			/* Generate a COOKIE ECHO chunk.  */			new_obj = sctp_make_cookie_echo(asoc, chunk);			if (!new_obj) {				if (cmd->obj.ptr)					sctp_chunk_free(cmd->obj.ptr);				goto nomem;			}			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,					SCTP_CHUNK(new_obj));			/* If there is an ERROR chunk to be sent along with			 * the COOKIE_ECHO, send it, too.			 */			if (cmd->obj.ptr)				sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,						SCTP_CHUNK(cmd->obj.ptr));			/* FIXME - Eventually come up with a cleaner way to			 * enabling COOKIE-ECHO + DATA bundling during			 * multihoming stale cookie scenarios, the following			 * command plays with asoc->peer.retran_path to			 * avoid the problem of sending the COOKIE-ECHO and			 * DATA in different paths, which could result			 * in the association being ABORTed if the DATA chunk			 * is processed first by the server.  Checking the			 * init error counter simply causes this command			 * to be executed only during failed attempts of			 * association establishment.			 */			if ((asoc->peer.retran_path !=			     asoc->peer.primary_path) &&			    (asoc->init_err_counter > 0)) {				sctp_add_cmd_sf(commands,						SCTP_CMD_FORCE_PRIM_RETRAN,						SCTP_NULL());			}			break;		case SCTP_CMD_GEN_SHUTDOWN:			/* Generate SHUTDOWN when in SHUTDOWN_SENT state.			 * Reset error counts.			 */			asoc->overall_error_count = 0;			/* Generate a SHUTDOWN chunk.  */			new_obj = sctp_make_shutdown(asoc, chunk);			if (!new_obj)				goto nomem;			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,					SCTP_CHUNK(new_obj));			break;		case SCTP_CMD_CHUNK_ULP:			/* Send a chunk to the sockets layer.  */			SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",					  "chunk_up:", cmd->obj.ptr,					  "ulpq:", &asoc->ulpq);			sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.ptr,					    GFP_ATOMIC);			break;		case SCTP_CMD_EVENT_ULP:			/* Send a notification to the sockets layer.  */			SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",					  "event_up:",cmd->obj.ptr,					  "ulpq:",&asoc->ulpq);			sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ptr);			break;		case SCTP_CMD_REPLY:			/* If an caller has not already corked, do cork. */			if (!asoc->outqueue.cork) {				sctp_outq_cork(&asoc->outqueue);				local_cork = 1;			}			/* Send a chunk to our peer.  */			error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr);			break;		case SCTP_CMD_SEND_PKT:			/* Send a full packet to our peer.  */			packet = cmd->obj.ptr;			sctp_packet_transmit(packet);			sctp_ootb_pkt_free(packet);			break;		case SCTP_CMD_T1_RETRAN:			/* Mark a transport for retransmission.  */			sctp_retransmit(&asoc->outqueue, cmd->obj.transport,					SCTP_RTXR_T1_RTX);			break;		case SCTP_CMD_RETRAN:			/* Mark a transport for retransmission.  */			sctp_retransmit(&asoc->outqueue, cmd->obj.transport,					SCTP_RTXR_T3_RTX);			break;		case SCTP_CMD_TRANSMIT:			/* Kick start transmission. */			error = sctp_outq_uncork(&asoc->outqueue);			local_cork = 0;			break;		case SCTP_CMD_ECN_CE:			/* Do delayed CE processing.   */			sctp_do_ecn_ce_work(asoc, cmd->obj.u32);			break;		case SCTP_CMD_ECN_ECNE:			/* Do delayed ECNE processing. */			new_obj = sctp_do_ecn_ecne_work(asoc, cmd->obj.u32,							chunk);			if (new_obj)				sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,						SCTP_CHUNK(new_obj));			break;		case SCTP_CMD_ECN_CWR:			/* Do delayed CWR processing.  */			sctp_do_ecn_cwr_work(asoc, cmd->obj.u32);			break;		case SCTP_CMD_SETUP_T2:			sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr);			break;		case SCTP_CMD_TIMER_START:			timer = &asoc->timers[cmd->obj.to];			timeout = asoc->timeouts[cmd->obj.to];			BUG_ON(!timeout);			timer->expires = jiffies + timeout;			sctp_association_hold(asoc);			add_timer(timer);			break;		case SCTP_CMD_TIMER_RESTART:			timer = &asoc->timers[cmd->obj.to];			timeout = asoc->timeouts[cmd->obj.to];			if (!mod_timer(timer, jiffies + timeout))				sctp_association_hold(asoc);			break;		case SCTP_CMD_TIMER_STOP:			timer = &asoc->timers[cmd->obj.to];			if (timer_pending(timer) && del_timer(timer))				sctp_association_put(asoc);			break;		case SCTP_CMD_INIT_CHOOSE_TRANSPORT:			chunk = cmd->obj.ptr;			t = sctp_assoc_choose_init_transport(asoc);			asoc->init_last_sent_to = t;			chunk->transport = t;			t->init_sent_count++;			break;		case SCTP_CMD_INIT_RESTART:			/* Do the needed accounting and updates			 * associated with restarting an initialization			 * timer. Only multiply the timeout by two if			 * all transports have been tried at the current			 * timeout.			 */			t = asoc->init_last_sent_to;			asoc->init_err_counter++;			if (t->init_sent_count > (asoc->init_cycle + 1)) {				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;				if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >				    asoc->max_init_timeo) {					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =						asoc->max_init_timeo;				}				asoc->init_cycle++;				SCTP_DEBUG_PRINTK(					"T1 INIT Timeout adjustment"					" init_err_counter: %d"					" cycle: %d"					" timeout: %ld\n",					asoc->init_err_counter,					asoc->init_cycle,					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);			}			sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));			break;		case SCTP_CMD_COOKIEECHO_RESTART:			/* Do the needed accounting and updates			 * associated with restarting an initialization			 * timer. Only multiply the timeout by two if			 * all transports have been tried at the current			 * timeout.			 */			asoc->init_err_counter++;			asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;			if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >			    asoc->max_init_timeo) {				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =					asoc->max_init_timeo;			}			SCTP_DEBUG_PRINTK(				"T1 COOKIE Timeout adjustment"				" init_err_counter: %d"				" timeout: %ld\n",				asoc->init_err_counter,				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);			/* If we've sent any data bundled with			 * COOKIE-ECHO we need to resend.			 */			list_for_each(pos, &asoc->peer.transport_addr_list) {				t = list_entry(pos, struct sctp_transport,					       transports);				sctp_retransmit_mark(&asoc->outqueue, t,					    SCTP_RTXR_T1_RTX);			}			sctp_add_cmd_sf(commands,					SCTP_CMD_TIMER_RESTART,					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));			break;		case SCTP_CMD_INIT_FAILED:			sctp_cmd_init_failed(commands, asoc, cmd->obj.err);			break;		case SCTP_CMD_ASSOC_FAILED:			sctp_cmd_assoc_failed(commands, asoc, event_type,					      subtype, chunk, cmd->obj.err);			break;		case SCTP_CMD_INIT_COUNTER_INC:			asoc->init_err_counter++;			break;		case SCTP_CMD_INIT_COUNTER_RESET:			asoc->init_err_counter = 0;			asoc->init_cycle = 0;			break;		case SCTP_CMD_REPORT_DUP:			sctp_tsnmap_mark_dup(&asoc->peer.tsn_map,					     cmd->obj.u32);			break;		case SCTP_CMD_REPORT_BAD_TAG:			SCTP_DEBUG_PRINTK("vtag mismatch!\n");			break;		case SCTP_CMD_STRIKE:			/* Mark one strike against a transport.  */			sctp_do_8_2_transport_strike(asoc, cmd->obj.transport);			break;		case SCTP_CMD_TRANSPORT_RESET:			t = cmd->obj.transport;			sctp_cmd_transport_reset(commands, asoc, t);			break;		case SCTP_CMD_TRANSPORT_ON:			t = cmd->obj.transport;			sctp_cmd_transport_on(commands, asoc, t, chunk);			break;		case SCTP_CMD_HB_TIMERS_START:			sctp_cmd_hb_timers_start(commands, asoc);			break;		case SCTP_CMD_HB_TIMER_UPDATE:			t = cmd->obj.transport;			sctp_cmd_hb_timer_update(commands, asoc, t);			break;		case SCTP_CMD_HB_TIMERS_STOP:			sctp_cmd_hb_timers_stop(commands, asoc);			break;		case SCTP_CMD_REPORT_ERROR:			error = cmd->obj.error;			break;		case SCTP_CMD_PROCESS_CTSN:			/* Dummy up a SACK for processing. */			sackh.cum_tsn_ack = cmd->obj.be32;			sackh.a_rwnd = 0;			sackh.num_gap_ack_blocks = 0;			sackh.num_dup_tsns = 0;			sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,					SCTP_SACKH(&sackh));			break;		case SCTP_CMD_DISCARD_PACKET:			/* We need to discard the whole packet.  */			chunk->pdiscard = 1;			break;		case SCTP_CMD_RTO_PENDING:			t = cmd->obj.transport;			t->rto_pending = 1;			break;		case SCTP_CMD_PART_DELIVER:			sctp_ulpq_partial_delivery(&asoc->ulpq, cmd->obj.ptr,						   GFP_ATOMIC);			break;		case SCTP_CMD_RENEGE:			sctp_ulpq_renege(&asoc->ulpq, cmd->obj.ptr,					 GFP_ATOMIC);			break;		case SCTP_CMD_SETUP_T4:			sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);			break;		case SCTP_CMD_PROCESS_OPERR:			sctp_cmd_process_operr(commands, asoc, chunk);			break;		case SCTP_CMD_CLEAR_INIT_TAG:			asoc->peer.i.init_tag = 0;			break;		case SCTP_CMD_DEL_NON_PRIMARY:			sctp_cmd_del_non_primary(asoc);			break;		case SCTP_CMD_T3_RTX_TIMERS_STOP:			sctp_cmd_t3_rtx_timers_stop(commands, asoc);			break;		case SCTP_CMD_FORCE_PRIM_RETRAN:			t = asoc->peer.retran_path;			asoc->peer.retran_path = asoc->peer.primary_path;			error = sctp_outq_uncork(&asoc->outqueue);			local_cork = 0;			asoc->peer.retran_path = t;			break;		case SCTP_CMD_SET_SK_ERR:			sctp_cmd_set_sk_err(asoc, cmd->obj.error);			break;		case SCTP_CMD_ASSOC_CHANGE:			sctp_cmd_assoc_change(commands, asoc,					      cmd->obj.u8);			break;		case SCTP_CMD_ADAPTATION_IND:			sctp_cmd_adaptation_ind(commands, asoc);			break;		case SCTP_CMD_ASSOC_SHKEY:			error = sctp_auth_asoc_init_active_key(asoc,						GFP_ATOMIC);			break;		case SCTP_CMD_UPDATE_INITTAG:			asoc->peer.i.init_tag = cmd->obj.u32;			break;		default:			printk(KERN_WARNING "Impossible command: %u, %p\n",			       cmd->verb, cmd->obj.ptr);			break;		}		if (error)			break;	}out:	if (local_cork)		sctp_outq_uncork(&asoc->outqueue);	return error;nomem:	error = -ENOMEM;	goto out;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -