📄 bearer.c
字号:
}void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest){ tipc_nmap_remove(&b_ptr->nodes, dest); tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort();}/* * bearer_push(): Resolve bearer congestion. Force the waiting * links to push out their unsent packets, one packet per link * per iteration, until all packets are gone or congestion reoccurs. * 'tipc_net_lock' is read_locked when this function is called * bearer.lock must be taken before calling * Returns binary true(1) ore false(0) */static int bearer_push(struct bearer *b_ptr){ u32 res = TIPC_OK; struct link *ln, *tln; if (b_ptr->publ.blocked) return 0; while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { res = tipc_link_push_packet(ln); if (res == PUSH_FAILED) break; if (res == PUSH_FINISHED) list_move_tail(&ln->link_list, &b_ptr->links); } } return list_empty(&b_ptr->cong_links);}void tipc_bearer_lock_push(struct bearer *b_ptr){ int res; spin_lock_bh(&b_ptr->publ.lock); res = bearer_push(b_ptr); spin_unlock_bh(&b_ptr->publ.lock); if (res) tipc_bcbearer_push();}/* * Interrupt enabling new requests after bearer congestion or blocking: * See bearer_send(). */void tipc_continue(struct tipc_bearer *tb_ptr){ struct bearer *b_ptr = (struct bearer *)tb_ptr; spin_lock_bh(&b_ptr->publ.lock); b_ptr->continue_count++; if (!list_empty(&b_ptr->cong_links)) tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); b_ptr->publ.blocked = 0; spin_unlock_bh(&b_ptr->publ.lock);}/* * Schedule link for sending of messages after the bearer * has been deblocked by 'continue()'. This method is called * when somebody tries to send a message via this link while * the bearer is congested. 'tipc_net_lock' is in read_lock here * bearer.lock is busy */static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr){ list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);}/* * Schedule link for sending of messages after the bearer * has been deblocked by 'continue()'. This method is called * when somebody tries to send a message via this link while * the bearer is congested. 'tipc_net_lock' is in read_lock here, * bearer.lock is free */void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr){ spin_lock_bh(&b_ptr->publ.lock); tipc_bearer_schedule_unlocked(b_ptr, l_ptr); spin_unlock_bh(&b_ptr->publ.lock);}/* * tipc_bearer_resolve_congestion(): Check if there is bearer congestion, * and if there is, try to resolve it before returning. * 'tipc_net_lock' is read_locked when this function is called */int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr){ int res = 1; if (list_empty(&b_ptr->cong_links)) return 1; spin_lock_bh(&b_ptr->publ.lock); if (!bearer_push(b_ptr)) { tipc_bearer_schedule_unlocked(b_ptr, l_ptr); res = 0; } spin_unlock_bh(&b_ptr->publ.lock); return res;}/** * tipc_enable_bearer - enable bearer with the given name */int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority){ struct bearer *b_ptr; struct media *m_ptr; struct bearer_name b_name; char addr_string[16]; u32 bearer_id; u32 with_this_prio; u32 i; int res = -EINVAL; if (tipc_mode != TIPC_NET_MODE) { warn("Bearer <%s> rejected, not supported in standalone mode\n", name); return -ENOPROTOOPT; } if (!bearer_name_validate(name, &b_name)) { warn("Bearer <%s> rejected, illegal name\n", name); return -EINVAL; } if (!tipc_addr_domain_valid(bcast_scope) || !in_scope(bcast_scope, tipc_own_addr)) { warn("Bearer <%s> rejected, illegal broadcast scope\n", name); return -EINVAL; } if ((priority < TIPC_MIN_LINK_PRI || priority > TIPC_MAX_LINK_PRI) && (priority != TIPC_MEDIA_LINK_PRI)) { warn("Bearer <%s> rejected, illegal priority\n", name); return -EINVAL; } write_lock_bh(&tipc_net_lock); m_ptr = media_find(b_name.media_name); if (!m_ptr) { warn("Bearer <%s> rejected, media <%s> not registered\n", name, b_name.media_name); goto failed; } if (priority == TIPC_MEDIA_LINK_PRI) priority = m_ptr->priority;restart: bearer_id = MAX_BEARERS; with_this_prio = 1; for (i = MAX_BEARERS; i-- != 0; ) { if (!tipc_bearers[i].active) { bearer_id = i; continue; } if (!strcmp(name, tipc_bearers[i].publ.name)) { warn("Bearer <%s> rejected, already enabled\n", name); goto failed; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { warn("Bearer <%s> rejected, duplicate priority\n", name); goto failed; } warn("Bearer <%s> priority adjustment required %u->%u\n", name, priority + 1, priority); goto restart; } } if (bearer_id >= MAX_BEARERS) { warn("Bearer <%s> rejected, bearer limit reached (%u)\n", name, MAX_BEARERS); goto failed; } b_ptr = &tipc_bearers[bearer_id]; memset(b_ptr, 0, sizeof(struct bearer)); strcpy(b_ptr->publ.name, name); res = m_ptr->enable_bearer(&b_ptr->publ); if (res) { warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); goto failed; } b_ptr->identity = bearer_id; b_ptr->media = m_ptr; b_ptr->net_plane = bearer_id + 'A'; b_ptr->active = 1; b_ptr->detect_scope = bcast_scope; b_ptr->priority = priority; INIT_LIST_HEAD(&b_ptr->cong_links); INIT_LIST_HEAD(&b_ptr->links); if (m_ptr->bcast) { b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, bcast_scope, 2); } spin_lock_init(&b_ptr->publ.lock); write_unlock_bh(&tipc_net_lock); info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, addr_string_fill(addr_string, bcast_scope), priority); return 0;failed: write_unlock_bh(&tipc_net_lock); return res;}/** * tipc_block_bearer(): Block the bearer with the given name, * and reset all its links */int tipc_block_bearer(const char *name){ struct bearer *b_ptr = NULL; struct link *l_ptr; struct link *temp_l_ptr; read_lock_bh(&tipc_net_lock); b_ptr = bearer_find(name); if (!b_ptr) { warn("Attempt to block unknown bearer <%s>\n", name); read_unlock_bh(&tipc_net_lock); return -EINVAL; } info("Blocking bearer <%s>\n", name); spin_lock_bh(&b_ptr->publ.lock); b_ptr->publ.blocked = 1; list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { struct node *n_ptr = l_ptr->owner; spin_lock_bh(&n_ptr->lock); tipc_link_reset(l_ptr); spin_unlock_bh(&n_ptr->lock); } spin_unlock_bh(&b_ptr->publ.lock); read_unlock_bh(&tipc_net_lock); return TIPC_OK;}/** * bearer_disable - * * Note: This routine assumes caller holds tipc_net_lock. */static int bearer_disable(const char *name){ struct bearer *b_ptr; struct link *l_ptr; struct link *temp_l_ptr; b_ptr = bearer_find(name); if (!b_ptr) { warn("Attempt to disable unknown bearer <%s>\n", name); return -EINVAL; } info("Disabling bearer <%s>\n", name); tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->publ.lock); b_ptr->link_req = NULL; b_ptr->publ.blocked = 1; if (b_ptr->media->disable_bearer) { spin_unlock_bh(&b_ptr->publ.lock); write_unlock_bh(&tipc_net_lock); b_ptr->media->disable_bearer(&b_ptr->publ); write_lock_bh(&tipc_net_lock); spin_lock_bh(&b_ptr->publ.lock); } list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { tipc_link_delete(l_ptr); } spin_unlock_bh(&b_ptr->publ.lock); memset(b_ptr, 0, sizeof(struct bearer)); return TIPC_OK;}int tipc_disable_bearer(const char *name){ int res; write_lock_bh(&tipc_net_lock); res = bearer_disable(name); write_unlock_bh(&tipc_net_lock); return res;}int tipc_bearer_init(void){ int res; write_lock_bh(&tipc_net_lock); tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC); media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC); if (tipc_bearers && media_list) { res = TIPC_OK; } else { kfree(tipc_bearers); kfree(media_list); tipc_bearers = NULL; media_list = NULL; res = -ENOMEM; } write_unlock_bh(&tipc_net_lock); return res;}void tipc_bearer_stop(void){ u32 i; if (!tipc_bearers) return; for (i = 0; i < MAX_BEARERS; i++) { if (tipc_bearers[i].active) tipc_bearers[i].publ.blocked = 1; } for (i = 0; i < MAX_BEARERS; i++) { if (tipc_bearers[i].active) bearer_disable(tipc_bearers[i].publ.name); } kfree(tipc_bearers); kfree(media_list); tipc_bearers = NULL; media_list = NULL; media_count = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -