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

📄 link.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		err("Attempt to delete non-existent link\n");		return;	}	dbg("tipc_link_delete()\n");	k_cancel_timer(&l_ptr->timer);	tipc_node_lock(l_ptr->owner);	tipc_link_reset(l_ptr);	tipc_node_detach_link(l_ptr->owner, l_ptr);	tipc_link_stop(l_ptr);	list_del_init(&l_ptr->link_list);	if (LINK_LOG_BUF_SIZE)		kfree(l_ptr->print_buf.buf);	tipc_node_unlock(l_ptr->owner);	k_term_timer(&l_ptr->timer);	kfree(l_ptr);}void tipc_link_start(struct link *l_ptr){	dbg("tipc_link_start %x\n", l_ptr);	link_state_event(l_ptr, STARTING_EVT);}/** * link_schedule_port - schedule port for deferred sending * @l_ptr: pointer to link * @origport: reference to sending port * @sz: amount of data to be sent * * Schedules port for renewed sending of messages after link congestion * has abated. */static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz){	struct port *p_ptr;	spin_lock_bh(&tipc_port_list_lock);	p_ptr = tipc_port_lock(origport);	if (p_ptr) {		if (!p_ptr->wakeup)			goto exit;		if (!list_empty(&p_ptr->wait_list))			goto exit;		p_ptr->congested_link = l_ptr;		p_ptr->publ.congested = 1;		p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr));		list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);		l_ptr->stats.link_congs++;exit:		tipc_port_unlock(p_ptr);	}	spin_unlock_bh(&tipc_port_list_lock);	return -ELINKCONG;}void tipc_link_wakeup_ports(struct link *l_ptr, int all){	struct port *p_ptr;	struct port *temp_p_ptr;	int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;	if (all)		win = 100000;	if (win <= 0)		return;	if (!spin_trylock_bh(&tipc_port_list_lock))		return;	if (link_congested(l_ptr))		goto exit;	list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports,				 wait_list) {		if (win <= 0)			break;		list_del_init(&p_ptr->wait_list);		p_ptr->congested_link = NULL;		spin_lock_bh(p_ptr->publ.lock);		p_ptr->publ.congested = 0;		p_ptr->wakeup(&p_ptr->publ);		win -= p_ptr->waiting_pkts;		spin_unlock_bh(p_ptr->publ.lock);	}exit:	spin_unlock_bh(&tipc_port_list_lock);}/** * link_release_outqueue - purge link's outbound message queue * @l_ptr: pointer to link */static void link_release_outqueue(struct link *l_ptr){	struct sk_buff *buf = l_ptr->first_out;	struct sk_buff *next;	while (buf) {		next = buf->next;		buf_discard(buf);		buf = next;	}	l_ptr->first_out = NULL;	l_ptr->out_queue_size = 0;}/** * tipc_link_reset_fragments - purge link's inbound message fragments queue * @l_ptr: pointer to link */void tipc_link_reset_fragments(struct link *l_ptr){	struct sk_buff *buf = l_ptr->defragm_buf;	struct sk_buff *next;	while (buf) {		next = buf->next;		buf_discard(buf);		buf = next;	}	l_ptr->defragm_buf = NULL;}/** * tipc_link_stop - purge all inbound and outbound messages associated with link * @l_ptr: pointer to link */void tipc_link_stop(struct link *l_ptr){	struct sk_buff *buf;	struct sk_buff *next;	buf = l_ptr->oldest_deferred_in;	while (buf) {		next = buf->next;		buf_discard(buf);		buf = next;	}	buf = l_ptr->first_out;	while (buf) {		next = buf->next;		buf_discard(buf);		buf = next;	}	tipc_link_reset_fragments(l_ptr);	buf_discard(l_ptr->proto_msg_queue);	l_ptr->proto_msg_queue = NULL;}#if 0/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */static void link_recv_event(struct link_event *ev){	ev->fcn(ev->addr, ev->name, ev->up);	kfree(ev);}static void link_send_event(void (*fcn)(u32 a, char *n, int up),			    struct link *l_ptr, int up){	struct link_event *ev;	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);	if (!ev) {		warn("Link event allocation failure\n");		return;	}	ev->addr = l_ptr->addr;	ev->up = up;	ev->fcn = fcn;	memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME);	tipc_k_signal((Handler)link_recv_event, (unsigned long)ev);}#else#define link_send_event(fcn, l_ptr, up) do { } while (0)#endifvoid tipc_link_reset(struct link *l_ptr){	struct sk_buff *buf;	u32 prev_state = l_ptr->state;	u32 checkpoint = l_ptr->next_in_no;	int was_active_link = tipc_link_is_active(l_ptr);	msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);	/* Link is down, accept any session: */	l_ptr->peer_session = 0;	/* Prepare for max packet size negotiation */	link_init_max_pkt(l_ptr);	l_ptr->state = RESET_UNKNOWN;	dbg_link_state("Resetting Link\n");	if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))		return;	tipc_node_link_down(l_ptr->owner, l_ptr);	tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);#if 0	tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);	dbg_link_dump();#endif	if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&	    l_ptr->owner->permit_changeover) {		l_ptr->reset_checkpoint = checkpoint;		l_ptr->exp_msg_count = START_CHANGEOVER;	}	/* Clean up all queues: */	link_release_outqueue(l_ptr);	buf_discard(l_ptr->proto_msg_queue);	l_ptr->proto_msg_queue = NULL;	buf = l_ptr->oldest_deferred_in;	while (buf) {		struct sk_buff *next = buf->next;		buf_discard(buf);		buf = next;	}	if (!list_empty(&l_ptr->waiting_ports))		tipc_link_wakeup_ports(l_ptr, 1);	l_ptr->retransm_queue_head = 0;	l_ptr->retransm_queue_size = 0;	l_ptr->last_out = NULL;	l_ptr->first_out = NULL;	l_ptr->next_out = NULL;	l_ptr->unacked_window = 0;	l_ptr->checkpoint = 1;	l_ptr->next_out_no = 1;	l_ptr->deferred_inqueue_sz = 0;	l_ptr->oldest_deferred_in = NULL;	l_ptr->newest_deferred_in = NULL;	l_ptr->fsm_msg_cnt = 0;	l_ptr->stale_count = 0;	link_reset_statistics(l_ptr);	link_send_event(tipc_cfg_link_event, l_ptr, 0);	if (!in_own_cluster(l_ptr->addr))		link_send_event(tipc_disc_link_event, l_ptr, 0);}static void link_activate(struct link *l_ptr){	l_ptr->next_in_no = l_ptr->stats.recv_info = 1;	tipc_node_link_up(l_ptr->owner, l_ptr);	tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);	link_send_event(tipc_cfg_link_event, l_ptr, 1);	if (!in_own_cluster(l_ptr->addr))		link_send_event(tipc_disc_link_event, l_ptr, 1);}/** * link_state_event - link finite state machine * @l_ptr: pointer to link * @event: state machine event to process */static void link_state_event(struct link *l_ptr, unsigned event){	struct link *other;	u32 cont_intv = l_ptr->continuity_interval;	if (!l_ptr->started && (event != STARTING_EVT))		return;		/* Not yet. */	if (link_blocked(l_ptr)) {		if (event == TIMEOUT_EVT) {			link_set_timer(l_ptr, cont_intv);		}		return;	  /* Changeover going on */	}	dbg_link("STATE_EV: <%s> ", l_ptr->name);	switch (l_ptr->state) {	case WORKING_WORKING:		dbg_link("WW/");		switch (event) {		case TRAFFIC_MSG_EVT:			dbg_link("TRF-");			/* fall through */		case ACTIVATE_MSG:			dbg_link("ACT\n");			break;		case TIMEOUT_EVT:			dbg_link("TIM ");			if (l_ptr->next_in_no != l_ptr->checkpoint) {				l_ptr->checkpoint = l_ptr->next_in_no;				if (tipc_bclink_acks_missing(l_ptr->owner)) {					tipc_link_send_proto_msg(l_ptr, STATE_MSG,								 0, 0, 0, 0, 0);					l_ptr->fsm_msg_cnt++;				} else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {					tipc_link_send_proto_msg(l_ptr, STATE_MSG,								 1, 0, 0, 0, 0);					l_ptr->fsm_msg_cnt++;				}				link_set_timer(l_ptr, cont_intv);				break;			}			dbg_link(" -> WU\n");			l_ptr->state = WORKING_UNKNOWN;			l_ptr->fsm_msg_cnt = 0;			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv / 4);			break;		case RESET_MSG:			dbg_link("RES -> RR\n");			info("Resetting link <%s>, requested by peer\n",			     l_ptr->name);			tipc_link_reset(l_ptr);			l_ptr->state = RESET_RESET;			l_ptr->fsm_msg_cnt = 0;			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		default:			err("Unknown link event %u in WW state\n", event);		}		break;	case WORKING_UNKNOWN:		dbg_link("WU/");		switch (event) {		case TRAFFIC_MSG_EVT:			dbg_link("TRF-");		case ACTIVATE_MSG:			dbg_link("ACT -> WW\n");			l_ptr->state = WORKING_WORKING;			l_ptr->fsm_msg_cnt = 0;			link_set_timer(l_ptr, cont_intv);			break;		case RESET_MSG:			dbg_link("RES -> RR\n");			info("Resetting link <%s>, requested by peer "			     "while probing\n", l_ptr->name);			tipc_link_reset(l_ptr);			l_ptr->state = RESET_RESET;			l_ptr->fsm_msg_cnt = 0;			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		case TIMEOUT_EVT:			dbg_link("TIM ");			if (l_ptr->next_in_no != l_ptr->checkpoint) {				dbg_link("-> WW \n");				l_ptr->state = WORKING_WORKING;				l_ptr->fsm_msg_cnt = 0;				l_ptr->checkpoint = l_ptr->next_in_no;				if (tipc_bclink_acks_missing(l_ptr->owner)) {					tipc_link_send_proto_msg(l_ptr, STATE_MSG,								 0, 0, 0, 0, 0);					l_ptr->fsm_msg_cnt++;				}				link_set_timer(l_ptr, cont_intv);			} else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {				dbg_link("Probing %u/%u,timer = %u ms)\n",					 l_ptr->fsm_msg_cnt, l_ptr->abort_limit,					 cont_intv / 4);				tipc_link_send_proto_msg(l_ptr, STATE_MSG,							 1, 0, 0, 0, 0);				l_ptr->fsm_msg_cnt++;				link_set_timer(l_ptr, cont_intv / 4);			} else {	/* Link has failed */				dbg_link("-> RU (%u probes unanswered)\n",					 l_ptr->fsm_msg_cnt);				warn("Resetting link <%s>, peer not responding\n",				     l_ptr->name);				tipc_link_reset(l_ptr);				l_ptr->state = RESET_UNKNOWN;				l_ptr->fsm_msg_cnt = 0;				tipc_link_send_proto_msg(l_ptr, RESET_MSG,							 0, 0, 0, 0, 0);				l_ptr->fsm_msg_cnt++;				link_set_timer(l_ptr, cont_intv);			}			break;		default:			err("Unknown link event %u in WU state\n", event);		}		break;	case RESET_UNKNOWN:		dbg_link("RU/");		switch (event) {		case TRAFFIC_MSG_EVT:			dbg_link("TRF-\n");			break;		case ACTIVATE_MSG:			other = l_ptr->owner->active_links[0];			if (other && link_working_unknown(other)) {				dbg_link("ACT\n");				break;			}			dbg_link("ACT -> WW\n");			l_ptr->state = WORKING_WORKING;			l_ptr->fsm_msg_cnt = 0;			link_activate(l_ptr);			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		case RESET_MSG:			dbg_link("RES \n");			dbg_link(" -> RR\n");			l_ptr->state = RESET_RESET;			l_ptr->fsm_msg_cnt = 0;			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		case STARTING_EVT:			dbg_link("START-");			l_ptr->started = 1;			/* fall through */		case TIMEOUT_EVT:			dbg_link("TIM \n");			tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		default:			err("Unknown link event %u in RU state\n", event);		}		break;	case RESET_RESET:		dbg_link("RR/ ");		switch (event) {		case TRAFFIC_MSG_EVT:			dbg_link("TRF-");			/* fall through */		case ACTIVATE_MSG:			other = l_ptr->owner->active_links[0];			if (other && link_working_unknown(other)) {				dbg_link("ACT\n");				break;			}			dbg_link("ACT -> WW\n");			l_ptr->state = WORKING_WORKING;			l_ptr->fsm_msg_cnt = 0;			link_activate(l_ptr);			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			break;		case RESET_MSG:			dbg_link("RES\n");			break;		case TIMEOUT_EVT:			dbg_link("TIM\n");			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);			l_ptr->fsm_msg_cnt++;			link_set_timer(l_ptr, cont_intv);			dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt);			break;		default:			err("Unknown link event %u in RR state\n", event);		}		break;	default:		err("Unknown link state %u/%u\n", l_ptr->state, event);	}}/* * link_bundle_buf(): Append contents of a buffer to * the tail of an existing one. */static int link_bundle_buf(struct link *l_ptr,			   struct sk_buff *bundler,			   struct sk_buff *buf){	struct tipc_msg *bundler_msg = buf_msg(bundler);	struct tipc_msg *msg = buf_msg(buf);	u32 size = msg_size(msg);	u32 bundle_size = msg_size(bundler_msg);	u32 to_pos = align(bundle_size);	u32 pad = to_pos - bundle_size;	if (msg_user(bundler_msg) != MSG_BUNDLER)

⌨️ 快捷键说明

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