···2929 Saying Y here will open some advanced configuration for TIPC.3030 Most users do not need to bother; if unsure, just say N.31313232-config TIPC_NODES3333- int "Maximum number of nodes in a cluster"3434- depends on TIPC_ADVANCED3535- range 8 20473636- default "255"3737- help3838- Specifies how many nodes can be supported in a TIPC cluster.3939- Can range from 8 to 2047 nodes; default is 255.4040-4141- Setting this to a smaller value saves some memory;4242- setting it to higher allows for more nodes.4343-4432config TIPC_PORTS4533 int "Maximum number of ports in a node"4634 depends on TIPC_ADVANCED
+5-10
net/tipc/addr.c
···22 * net/tipc/addr.c: TIPC address utility routines33 *44 * Copyright (c) 2000-2006, Ericsson AB55- * Copyright (c) 2004-2005, Wind River Systems55+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···4141 * tipc_addr_domain_valid - validates a network domain address4242 *4343 * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,4444- * where Z, C, and N are non-zero and do not exceed the configured limits.4444+ * where Z, C, and N are non-zero.4545 *4646 * Returns 1 if domain address is valid, otherwise 04747 */···5151 u32 n = tipc_node(addr);5252 u32 c = tipc_cluster(addr);5353 u32 z = tipc_zone(addr);5454- u32 max_nodes = tipc_max_nodes;5555-5656- if (n > max_nodes)5757- return 0;58545955 if (n && (!z || !c))6056 return 0;···6266/**6367 * tipc_addr_node_valid - validates a proposed network address for this node6468 *6565- * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed6666- * the configured limits.6969+ * Accepts <Z.C.N>, where Z, C, and N are non-zero.6770 *6871 * Returns 1 if address can be used, otherwise 06972 */···7681{7782 if (!domain || (domain == addr))7883 return 1;7979- if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */8484+ if (domain == tipc_cluster_mask(addr)) /* domain <Z.C.0> */8085 return 1;8181- if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */8686+ if (domain == tipc_zone_mask(addr)) /* domain <Z.0.0> */8287 return 1;8388 return 0;8489}
···7070 * @disable_bearer: routine which disables a bearer7171 * @addr2str: routine which converts bearer's address to string form7272 * @bcast_addr: media address used in broadcasting7373- * @bcast: non-zero if media supports broadcasting [currently mandatory]7473 * @priority: default link (and bearer) priority7574 * @tolerance: default time (in ms) before declaring link failure7675 * @window: default window (in packets) before declaring link congestion···8687 char *(*addr2str)(struct tipc_media_addr *a,8788 char *str_buf, int str_size);8889 struct tipc_media_addr bcast_addr;8989- int bcast;9090 u32 priority;9191 u32 tolerance;9292 u32 window;···103105 * @name: bearer name (format = media:interface)104106 * @media: ptr to media structure associated with bearer105107 * @priority: default link priority for bearer106106- * @detect_scope: network address mask used during automatic link creation107108 * @identity: array index of this bearer within TIPC bearer array108109 * @link_req: ptr to (optional) structure making periodic link setup requests109110 * @links: list of non-congested links associated with bearer···125128 spinlock_t lock;126129 struct media *media;127130 u32 priority;128128- u32 detect_scope;129131 u32 identity;130132 struct link_req *link_req;131133 struct list_head links;···163167int tipc_block_bearer(const char *name);164168void tipc_continue(struct tipc_bearer *tb_ptr);165169166166-int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);170170+int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);167171int tipc_disable_bearer(const char *name);168172169173/*
+4-27
net/tipc/config.c
···22 * net/tipc/config.c: TIPC configuration management code33 *44 * Copyright (c) 2002-2006, Ericsson AB55- * Copyright (c) 2004-2007, Wind River Systems55+ * Copyright (c) 2004-2007, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···148148149149 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);150150 if (tipc_enable_bearer(args->name,151151- ntohl(args->detect_scope),151151+ ntohl(args->disc_domain),152152 ntohl(args->priority)))153153 return tipc_cfg_reply_error_string("unable to enable bearer");154154···257257 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED258258 " (cannot change max ports while TIPC is active)");259259 tipc_max_ports = value;260260- return tipc_cfg_reply_none();261261-}262262-263263-static struct sk_buff *cfg_set_max_nodes(void)264264-{265265- u32 value;266266-267267- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))268268- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);269269- value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));270270- if (value == tipc_max_nodes)271271- return tipc_cfg_reply_none();272272- if (value != delimit(value, 8, 2047))273273- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE274274- " (max nodes must be 8-2047)");275275- if (tipc_mode == TIPC_NET_MODE)276276- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED277277- " (cannot change max nodes once TIPC has joined a network)");278278- tipc_max_nodes = value;279260 return tipc_cfg_reply_none();280261}281262···378397 case TIPC_CMD_SET_MAX_SUBSCR:379398 rep_tlv_buf = cfg_set_max_subscriptions();380399 break;381381- case TIPC_CMD_SET_MAX_NODES:382382- rep_tlv_buf = cfg_set_max_nodes();383383- break;384400 case TIPC_CMD_SET_NETID:385401 rep_tlv_buf = cfg_set_netid();386402 break;···393415 case TIPC_CMD_GET_MAX_SUBSCR:394416 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);395417 break;396396- case TIPC_CMD_GET_MAX_NODES:397397- rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes);398398- break;399418 case TIPC_CMD_GET_NETID:400419 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);401420 break;···406431 case TIPC_CMD_GET_MAX_SLAVES:407432 case TIPC_CMD_SET_MAX_CLUSTERS:408433 case TIPC_CMD_GET_MAX_CLUSTERS:434434+ case TIPC_CMD_SET_MAX_NODES:435435+ case TIPC_CMD_GET_MAX_NODES:409436 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED410437 " (obsolete command)");411438 break;
···147147 */148148149149extern u32 tipc_own_addr;150150-extern int tipc_max_nodes;151150extern int tipc_max_ports;152151extern int tipc_max_subscriptions;153152extern int tipc_max_publications;
+61-44
net/tipc/discover.c
···7575 u32 dest_domain,7676 struct tipc_bearer *b_ptr)7777{7878- struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE);7878+ struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);7979 struct tipc_msg *msg;80808181 if (buf) {8282 msg = buf_msg(buf);8383- tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain);8383+ tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain);8484 msg_set_non_seq(msg, 1);8585 msg_set_dest_domain(msg, dest_domain);8686 msg_set_bc_netid(msg, tipc_net_id);···119119120120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)121121{122122+ struct tipc_node *n_ptr;122123 struct link *link;123123- struct tipc_media_addr media_addr;124124+ struct tipc_media_addr media_addr, *addr;125125+ struct sk_buff *rbuf;124126 struct tipc_msg *msg = buf_msg(buf);125127 u32 dest = msg_dest_domain(msg);126128 u32 orig = msg_prevnode(msg);127129 u32 net_id = msg_bc_netid(msg);128130 u32 type = msg_type(msg);131131+ int link_fully_up;129132130133 msg_get_media_addr(msg, &media_addr);131134 buf_discard(buf);132135136136+ /* Validate discovery message from requesting node */133137 if (net_id != tipc_net_id)134138 return;135139 if (!tipc_addr_domain_valid(dest))···147143 }148144 if (!tipc_in_scope(dest, tipc_own_addr))149145 return;150150- if (in_own_cluster(orig)) {151151- /* Always accept link here */152152- struct sk_buff *rbuf;153153- struct tipc_media_addr *addr;154154- struct tipc_node *n_ptr = tipc_node_find(orig);155155- int link_fully_up;146146+ if (!in_own_cluster(orig))147147+ return;156148157157- if (n_ptr == NULL) {158158- n_ptr = tipc_node_create(orig);159159- if (!n_ptr)160160- return;161161- }162162- spin_lock_bh(&n_ptr->lock);163163-164164- /* Don't talk to neighbor during cleanup after last session */165165-166166- if (n_ptr->cleanup_required) {167167- spin_unlock_bh(&n_ptr->lock);149149+ /* Locate structure corresponding to requesting node */150150+ n_ptr = tipc_node_find(orig);151151+ if (!n_ptr) {152152+ n_ptr = tipc_node_create(orig);153153+ if (!n_ptr)168154 return;169169- }155155+ }156156+ tipc_node_lock(n_ptr);170157171171- link = n_ptr->links[b_ptr->identity];158158+ /* Don't talk to neighbor during cleanup after last session */159159+ if (n_ptr->cleanup_required) {160160+ tipc_node_unlock(n_ptr);161161+ return;162162+ }163163+164164+ link = n_ptr->links[b_ptr->identity];165165+166166+ /* Create a link endpoint for this bearer, if necessary */167167+ if (!link) {168168+ link = tipc_link_create(n_ptr, b_ptr, &media_addr);172169 if (!link) {173173- link = tipc_link_create(b_ptr, orig, &media_addr);174174- if (!link) {175175- spin_unlock_bh(&n_ptr->lock);176176- return;177177- }178178- }179179- addr = &link->media_addr;180180- if (memcmp(addr, &media_addr, sizeof(*addr))) {181181- if (tipc_link_is_up(link) || (!link->started)) {182182- disc_dupl_alert(b_ptr, orig, &media_addr);183183- spin_unlock_bh(&n_ptr->lock);184184- return;185185- }186186- warn("Resetting link <%s>, peer interface address changed\n",187187- link->name);188188- memcpy(addr, &media_addr, sizeof(*addr));189189- tipc_link_reset(link);190190- }191191- link_fully_up = link_working_working(link);192192- spin_unlock_bh(&n_ptr->lock);193193- if ((type == DSC_RESP_MSG) || link_fully_up)170170+ tipc_node_unlock(n_ptr);194171 return;172172+ }173173+ }174174+175175+ /*176176+ * Ensure requesting node's media address is correct177177+ *178178+ * If media address doesn't match and the link is working, reject the179179+ * request (must be from a duplicate node).180180+ *181181+ * If media address doesn't match and the link is not working, accept182182+ * the new media address and reset the link to ensure it starts up183183+ * cleanly.184184+ */185185+ addr = &link->media_addr;186186+ if (memcmp(addr, &media_addr, sizeof(*addr))) {187187+ if (tipc_link_is_up(link) || (!link->started)) {188188+ disc_dupl_alert(b_ptr, orig, &media_addr);189189+ tipc_node_unlock(n_ptr);190190+ return;191191+ }192192+ warn("Resetting link <%s>, peer interface address changed\n",193193+ link->name);194194+ memcpy(addr, &media_addr, sizeof(*addr));195195+ tipc_link_reset(link);196196+ }197197+198198+ /* Accept discovery message & send response, if necessary */199199+ link_fully_up = link_working_working(link);200200+201201+ if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {195202 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);196196- if (rbuf != NULL) {203203+ if (rbuf) {197204 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);198205 buf_discard(rbuf);199206 }200207 }208208+209209+ tipc_node_unlock(n_ptr);201210}202211203212/**
+29-21
net/tipc/link.c
···293293294294/**295295 * tipc_link_create - create a new link296296+ * @n_ptr: pointer to associated node296297 * @b_ptr: pointer to associated bearer297297- * @peer: network address of node at other end of link298298 * @media_addr: media address to use when sending messages over link299299 *300300 * Returns pointer to link.301301 */302302303303-struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer,303303+struct link *tipc_link_create(struct tipc_node *n_ptr,304304+ struct tipc_bearer *b_ptr,304305 const struct tipc_media_addr *media_addr)305306{306307 struct link *l_ptr;307308 struct tipc_msg *msg;308309 char *if_name;310310+ char addr_string[16];311311+ u32 peer = n_ptr->addr;312312+313313+ if (n_ptr->link_cnt >= 2) {314314+ tipc_addr_string_fill(addr_string, n_ptr->addr);315315+ err("Attempt to establish third link to %s\n", addr_string);316316+ return NULL;317317+ }318318+319319+ if (n_ptr->links[b_ptr->identity]) {320320+ tipc_addr_string_fill(addr_string, n_ptr->addr);321321+ err("Attempt to establish second link on <%s> to %s\n",322322+ b_ptr->name, addr_string);323323+ return NULL;324324+ }309325310326 l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC);311327 if (!l_ptr) {···338322 tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));339323 /* note: peer i/f is appended to link name by reset/activate */340324 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));325325+ l_ptr->owner = n_ptr;341326 l_ptr->checkpoint = 1;342327 l_ptr->b_ptr = b_ptr;343328 link_set_supervision_props(l_ptr, b_ptr->media->tolerance);···362345363346 link_reset_statistics(l_ptr);364347365365- l_ptr->owner = tipc_node_attach_link(l_ptr);366366- if (!l_ptr->owner) {367367- kfree(l_ptr);368368- return NULL;369369- }348348+ tipc_node_attach_link(n_ptr, l_ptr);370349371350 k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);372351 list_add_tail(&l_ptr->link_list, &b_ptr->links);···561548 tipc_node_link_down(l_ptr->owner, l_ptr);562549 tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);563550564564- if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&551551+ if (was_active_link && tipc_node_active_links(l_ptr->owner) &&565552 l_ptr->owner->permit_changeover) {566553 l_ptr->reset_checkpoint = checkpoint;567554 l_ptr->exp_msg_count = START_CHANGEOVER;···17461733 tipc_node_unlock(n_ptr);17471734 tipc_link_recv_bundle(buf);17481735 continue;17491749- case ROUTE_DISTRIBUTOR:17501750- tipc_node_unlock(n_ptr);17511751- buf_discard(buf);17521752- continue;17531736 case NAME_DISTRIBUTOR:17541737 tipc_node_unlock(n_ptr);17551738 tipc_named_recv(buf);···17711762 goto deliver;17721763 goto protocol_check;17731764 }17651765+ break;17661766+ default:17671767+ buf_discard(buf);17681768+ buf = NULL;17741769 break;17751770 }17761771 }···19111898 struct sk_buff *buf = NULL;19121899 struct tipc_msg *msg = l_ptr->pmsg;19131900 u32 msg_size = sizeof(l_ptr->proto_msg);19011901+ int r_flag;1914190219151903 if (link_blocked(l_ptr))19161904 return;···19681954 msg_set_max_pkt(msg, l_ptr->max_pkt_target);19691955 }1970195619711971- if (tipc_node_has_redundant_links(l_ptr->owner))19721972- msg_set_redundant_link(msg);19731973- else19741974- msg_clear_redundant_link(msg);19571957+ r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr));19581958+ msg_set_redundant_link(msg, r_flag);19751959 msg_set_linkprio(msg, l_ptr->priority);1976196019771961 /* Ensure sequence number will not fit : */···19891977 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));19901978 return;19911979 }19921992- msg_set_timestamp(msg, jiffies_to_msecs(jiffies));1993198019941981 /* Message can be sent */19951982···20762065 l_ptr->peer_bearer_id = msg_bearer_id(msg);2077206620782067 /* Synchronize broadcast sequence numbers */20792079- if (!tipc_node_has_redundant_links(l_ptr->owner))20682068+ if (!tipc_node_redundant_links(l_ptr->owner))20802069 l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));20812070 break;20822071 case STATE_MSG:···24222411 destaddr = l_ptr->addr;24232412 else24242413 destaddr = msg_destnode(inmsg);24252425-24262426- if (msg_routed(inmsg))24272427- msg_set_prevnode(inmsg, tipc_own_addr);2428241424292415 /* Prepare reusable fragment header: */24302416
+2-1
net/tipc/link.h
···207207208208struct tipc_port;209209210210-struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer,210210+struct link *tipc_link_create(struct tipc_node *n_ptr,211211+ struct tipc_bearer *b_ptr,211212 const struct tipc_media_addr *media_addr);212213void tipc_link_delete(struct link *l_ptr);213214void tipc_link_changeover(struct link *l_ptr);
-34
net/tipc/msg.c
···192192 default:193193 tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg));194194 }195195- if (msg_routed(msg) && !msg_non_seq(msg))196196- tipc_printf(buf, "ROUT:");197195 if (msg_reroute_cnt(msg))198196 tipc_printf(buf, "REROUTED(%u):",199197 msg_reroute_cnt(msg));···208210 default:209211 tipc_printf(buf, "UNKNOWN:%x", msg_type(msg));210212 }211211- if (msg_routed(msg))212212- tipc_printf(buf, "ROUT:");213213 if (msg_reroute_cnt(msg))214214 tipc_printf(buf, "REROUTED(%u):",215215 msg_reroute_cnt(msg));···228232 default:229233 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));230234 }231231- if (msg_routed(msg))232232- tipc_printf(buf, "ROUT:");233235 if (msg_reroute_cnt(msg))234236 tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg));235237 break;236238 case LINK_PROTOCOL:237237- tipc_printf(buf, "PROT:TIM(%u):", msg_timestamp(msg));238239 switch (msg_type(msg)) {239240 case STATE_MSG:240241 tipc_printf(buf, "STATE:");···263270 case ORIGINAL_MSG:264271 tipc_printf(buf, "ORIG:");265272 tipc_printf(buf, "EXP(%u)", msg_msgcnt(msg));266266- break;267267- default:268268- tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));269269- }270270- break;271271- case ROUTE_DISTRIBUTOR:272272- tipc_printf(buf, "ROUTING_MNG:");273273- switch (msg_type(msg)) {274274- case EXT_ROUTING_TABLE:275275- tipc_printf(buf, "EXT_TBL:");276276- tipc_printf(buf, "TO:%x:", msg_remote_node(msg));277277- break;278278- case LOCAL_ROUTING_TABLE:279279- tipc_printf(buf, "LOCAL_TBL:");280280- tipc_printf(buf, "TO:%x:", msg_remote_node(msg));281281- break;282282- case SLAVE_ROUTING_TABLE:283283- tipc_printf(buf, "DP_TBL:");284284- tipc_printf(buf, "TO:%x:", msg_remote_node(msg));285285- break;286286- case ROUTE_ADDITION:287287- tipc_printf(buf, "ADD:");288288- tipc_printf(buf, "TO:%x:", msg_remote_node(msg));289289- break;290290- case ROUTE_REMOVAL:291291- tipc_printf(buf, "REMOVE:");292292- tipc_printf(buf, "TO:%x:", msg_remote_node(msg));293273 break;294274 default:295275 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
···22 * net/tipc/name_distr.c: TIPC name distribution code33 *44 * Copyright (c) 2000-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···109109{110110 struct sk_buff *buf_copy;111111 struct tipc_node *n_ptr;112112- u32 n_num;113112114114- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {115115- n_ptr = tipc_net.nodes[n_num];116116- if (n_ptr && tipc_node_has_active_links(n_ptr)) {113113+ list_for_each_entry(n_ptr, &tipc_node_list, list) {114114+ if (tipc_node_active_links(n_ptr)) {117115 buf_copy = skb_copy(buf, GFP_ATOMIC);118116 if (!buf_copy)119117 break;···212214}213215214216/**215215- * node_is_down - remove publication associated with a failed node217217+ * named_purge_publ - remove publication associated with a failed node216218 *217219 * Invoked for each publication issued by a newly failed node.218220 * Removes publication structure from name table & deletes it.219221 * In rare cases the link may have come back up again when this220222 * function is called, and we have two items representing the same221223 * publication. Nudge this item's key to distinguish it from the other.222222- * (Note: Publication's node subscription is already unsubscribed.)223224 */224225225225-static void node_is_down(struct publication *publ)226226+static void named_purge_publ(struct publication *publ)226227{227228 struct publication *p;228229···229232 publ->key += 1222345;230233 p = tipc_nametbl_remove_publ(publ->type, publ->lower,231234 publ->node, publ->ref, publ->key);235235+ if (p)236236+ tipc_nodesub_unsubscribe(&p->subscr);232237 write_unlock_bh(&tipc_nametbl_lock);233238234239 if (p != publ) {···267268 tipc_nodesub_subscribe(&publ->subscr,268269 msg_orignode(msg),269270 publ,270270- (net_ev_handler)node_is_down);271271+ (net_ev_handler)272272+ named_purge_publ);271273 }272274 } else if (msg_type(msg) == WITHDRAWAL) {273275 publ = tipc_nametbl_remove_publ(ntohl(item->type),
+6-26
net/tipc/net.c
···22 * net/tipc/net.c: TIPC network routing code33 *44 * Copyright (c) 1995-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···3939#include "name_distr.h"4040#include "subscr.h"4141#include "port.h"4242+#include "node.h"4243#include "config.h"43444445/*···109108*/110109111110DEFINE_RWLOCK(tipc_net_lock);112112-struct network tipc_net;113113-114114-static int net_start(void)115115-{116116- tipc_net.nodes = kcalloc(tipc_max_nodes + 1,117117- sizeof(*tipc_net.nodes), GFP_ATOMIC);118118- tipc_net.highest_node = 0;119119-120120- return tipc_net.nodes ? 0 : -ENOMEM;121121-}122122-123123-static void net_stop(void)124124-{125125- u32 n_num;126126-127127- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++)128128- tipc_node_delete(tipc_net.nodes[n_num]);129129- kfree(tipc_net.nodes);130130- tipc_net.nodes = NULL;131131-}132111133112static void net_route_named_msg(struct sk_buff *buf)134113{···198217 tipc_named_reinit();199218 tipc_port_reinit();200219201201- res = net_start();202202- if (res)203203- return res;204220 res = tipc_bclink_init();205221 if (res)206222 return res;···213235214236void tipc_net_stop(void)215237{238238+ struct tipc_node *node, *t_node;239239+216240 if (tipc_mode != TIPC_NET_MODE)217241 return;218242 write_lock_bh(&tipc_net_lock);219243 tipc_bearer_stop();220244 tipc_mode = TIPC_NODE_MODE;221245 tipc_bclink_stop();222222- net_stop();246246+ list_for_each_entry_safe(node, t_node, &tipc_node_list, list);247247+ tipc_node_delete(node);223248 write_unlock_bh(&tipc_net_lock);224249 info("Left network mode\n");225250}226226-
+1-18
net/tipc/net.h
···22 * net/tipc/net.h: Include file for TIPC network routing code33 *44 * Copyright (c) 1995-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···3737#ifndef _TIPC_NET_H3838#define _TIPC_NET_H39394040-struct tipc_node;4141-4242-/**4343- * struct network - TIPC network structure4444- * @nodes: array of pointers to all nodes within cluster4545- * @highest_node: id of highest numbered node within cluster4646- * @links: number of (unicast) links to cluster4747- */4848-4949-struct network {5050- struct tipc_node **nodes;5151- u32 highest_node;5252- u32 links;5353-};5454-5555-5656-extern struct network tipc_net;5740extern rwlock_t tipc_net_lock;58415942void tipc_net_route_msg(struct sk_buff *buf);
+57-66
net/tipc/node.c
···44444545static DEFINE_SPINLOCK(node_create_lock);46464747+static struct hlist_head node_htable[NODE_HTABLE_SIZE];4848+LIST_HEAD(tipc_node_list);4949+static u32 tipc_num_nodes;5050+5151+static atomic_t tipc_num_links = ATOMIC_INIT(0);4752u32 tipc_own_tag;5353+5454+/**5555+ * tipc_node_find - locate specified node object, if it exists5656+ */5757+5858+struct tipc_node *tipc_node_find(u32 addr)5959+{6060+ struct tipc_node *node;6161+ struct hlist_node *pos;6262+6363+ if (unlikely(!in_own_cluster(addr)))6464+ return NULL;6565+6666+ hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {6767+ if (node->addr == addr)6868+ return node;6969+ }7070+ return NULL;7171+}48724973/**5074 * tipc_node_create - create neighboring node···82588359struct tipc_node *tipc_node_create(u32 addr)8460{8585- struct tipc_node *n_ptr;8686- u32 n_num;6161+ struct tipc_node *n_ptr, *temp_node;87628863 spin_lock_bh(&node_create_lock);8964···1017810279 n_ptr->addr = addr;10380 spin_lock_init(&n_ptr->lock);8181+ INIT_HLIST_NODE(&n_ptr->hash);8282+ INIT_LIST_HEAD(&n_ptr->list);10483 INIT_LIST_HEAD(&n_ptr->nsub);10584106106- n_num = tipc_node(addr);107107- tipc_net.nodes[n_num] = n_ptr;108108- if (n_num > tipc_net.highest_node)109109- tipc_net.highest_node = n_num;8585+ hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);8686+8787+ list_for_each_entry(temp_node, &tipc_node_list, list) {8888+ if (n_ptr->addr < temp_node->addr)8989+ break;9090+ }9191+ list_add_tail(&n_ptr->list, &temp_node->list);9292+9393+ tipc_num_nodes++;1109411195 spin_unlock_bh(&node_create_lock);11296 return n_ptr;···1219112292void tipc_node_delete(struct tipc_node *n_ptr)12393{124124- u32 n_num;125125-126126- if (!n_ptr)127127- return;128128-129129- n_num = tipc_node(n_ptr->addr);130130- tipc_net.nodes[n_num] = NULL;9494+ list_del(&n_ptr->list);9595+ hlist_del(&n_ptr->hash);13196 kfree(n_ptr);13297133133- while (!tipc_net.nodes[tipc_net.highest_node])134134- if (--tipc_net.highest_node == 0)135135- break;9898+ tipc_num_nodes--;13699}137100138101···223200 node_lost_contact(n_ptr);224201}225202226226-int tipc_node_has_active_links(struct tipc_node *n_ptr)203203+int tipc_node_active_links(struct tipc_node *n_ptr)227204{228205 return n_ptr->active_links[0] != NULL;229206}230207231231-int tipc_node_has_redundant_links(struct tipc_node *n_ptr)208208+int tipc_node_redundant_links(struct tipc_node *n_ptr)232209{233210 return n_ptr->working_links > 1;234211}235212236213int tipc_node_is_up(struct tipc_node *n_ptr)237214{238238- return tipc_node_has_active_links(n_ptr);215215+ return tipc_node_active_links(n_ptr);239216}240217241241-struct tipc_node *tipc_node_attach_link(struct link *l_ptr)218218+void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)242219{243243- struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr);244244-245245- if (!n_ptr)246246- n_ptr = tipc_node_create(l_ptr->addr);247247- if (n_ptr) {248248- u32 bearer_id = l_ptr->b_ptr->identity;249249- char addr_string[16];250250-251251- if (n_ptr->link_cnt >= 2) {252252- err("Attempt to create third link to %s\n",253253- tipc_addr_string_fill(addr_string, n_ptr->addr));254254- return NULL;255255- }256256-257257- if (!n_ptr->links[bearer_id]) {258258- n_ptr->links[bearer_id] = l_ptr;259259- tipc_net.links++;260260- n_ptr->link_cnt++;261261- return n_ptr;262262- }263263- err("Attempt to establish second link on <%s> to %s\n",264264- l_ptr->b_ptr->name,265265- tipc_addr_string_fill(addr_string, l_ptr->addr));266266- }267267- return NULL;220220+ n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;221221+ atomic_inc(&tipc_num_links);222222+ n_ptr->link_cnt++;268223}269224270225void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)271226{272227 n_ptr->links[l_ptr->b_ptr->identity] = NULL;273273- tipc_net.links--;228228+ atomic_dec(&tipc_num_links);274229 n_ptr->link_cnt--;275230}276231···328327329328static void node_lost_contact(struct tipc_node *n_ptr)330329{331331- struct tipc_node_subscr *ns, *tns;332330 char addr_string[16];333331 u32 i;334332···365365 }366366367367 /* Notify subscribers */368368- list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {369369- ns->node = NULL;370370- list_del_init(&ns->nodesub_list);371371- tipc_k_signal((Handler)ns->handle_node_down,372372- (unsigned long)ns->usr_handle);373373- }368368+ tipc_nodesub_notify(n_ptr);374369375370 /* Prevent re-contact with node until all cleanup is done */376371···380385 struct tipc_node *n_ptr;381386 struct tipc_node_info node_info;382387 u32 payload_size;383383- u32 n_num;384388385389 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))386390 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);···390396 " (network address)");391397392398 read_lock_bh(&tipc_net_lock);393393- if (!tipc_net.nodes) {399399+ if (!tipc_num_nodes) {394400 read_unlock_bh(&tipc_net_lock);395401 return tipc_cfg_reply_none();396402 }397403398404 /* For now, get space for all other nodes */399405400400- payload_size = TLV_SPACE(sizeof(node_info)) *401401- (tipc_net.highest_node - 1);406406+ payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;402407 if (payload_size > 32768u) {403408 read_unlock_bh(&tipc_net_lock);404409 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED···411418412419 /* Add TLVs for all nodes in scope */413420414414- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {415415- n_ptr = tipc_net.nodes[n_num];416416- if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))421421+ list_for_each_entry(n_ptr, &tipc_node_list, list) {422422+ if (!tipc_in_scope(domain, n_ptr->addr))417423 continue;418424 node_info.addr = htonl(n_ptr->addr);419425 node_info.up = htonl(tipc_node_is_up(n_ptr));···431439 struct tipc_node *n_ptr;432440 struct tipc_link_info link_info;433441 u32 payload_size;434434- u32 n_num;435442436443 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))437444 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);···447456448457 /* Get space for all unicast links + multicast link */449458450450- payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1);459459+ payload_size = TLV_SPACE(sizeof(link_info)) *460460+ (atomic_read(&tipc_num_links) + 1);451461 if (payload_size > 32768u) {452462 read_unlock_bh(&tipc_net_lock);453463 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED···462470463471 /* Add TLV for broadcast link */464472465465- link_info.dest = htonl(tipc_own_addr & 0xfffff00);473473+ link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));466474 link_info.up = htonl(1);467475 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);468476 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));469477470478 /* Add TLVs for any other links in scope */471479472472- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {480480+ list_for_each_entry(n_ptr, &tipc_node_list, list) {473481 u32 i;474482475475- n_ptr = tipc_net.nodes[n_num];476476- if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))483483+ if (!tipc_in_scope(domain, n_ptr->addr))477484 continue;478485 tipc_node_lock(n_ptr);479486 for (i = 0; i < MAX_BEARERS; i++) {
+23-13
net/tipc/node.h
···22 * net/tipc/node.h: Include file for TIPC node management routines33 *44 * Copyright (c) 2000-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···4646 * struct tipc_node - TIPC node structure4747 * @addr: network address of node4848 * @lock: spinlock governing access to structure4949- * @next: pointer to next node in sorted list of cluster's nodes4949+ * @hash: links to adjacent nodes in unsorted hash chain5050+ * @list: links to adjacent nodes in sorted list of cluster's nodes5051 * @nsub: list of "node down" subscriptions monitoring node5152 * @active_links: pointers to active links to node5253 * @links: pointers to all links to node···7069struct tipc_node {7170 u32 addr;7271 spinlock_t lock;7373- struct tipc_node *next;7272+ struct hlist_node hash;7373+ struct list_head list;7474 struct list_head nsub;7575 struct link *active_links[2];7676 struct link *links[MAX_BEARERS];···9290 } bclink;9391};94929393+#define NODE_HTABLE_SIZE 5129494+extern struct list_head tipc_node_list;9595+9696+/*9797+ * A trivial power-of-two bitmask technique is used for speed, since this9898+ * operation is done for every incoming TIPC packet. The number of hash table9999+ * entries has been chosen so that no hash chain exceeds 8 nodes and will100100+ * usually be much smaller (typically only a single node).101101+ */102102+static inline unsigned int tipc_hashfn(u32 addr)103103+{104104+ return addr & (NODE_HTABLE_SIZE - 1);105105+}106106+95107extern u32 tipc_own_tag;96108109109+struct tipc_node *tipc_node_find(u32 addr);97110struct tipc_node *tipc_node_create(u32 addr);98111void tipc_node_delete(struct tipc_node *n_ptr);9999-struct tipc_node *tipc_node_attach_link(struct link *l_ptr);112112+void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr);100113void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr);101114void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr);102115void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr);103103-int tipc_node_has_active_links(struct tipc_node *n_ptr);104104-int tipc_node_has_redundant_links(struct tipc_node *n_ptr);116116+int tipc_node_active_links(struct tipc_node *n_ptr);117117+int tipc_node_redundant_links(struct tipc_node *n_ptr);105118int tipc_node_is_up(struct tipc_node *n_ptr);106119struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);107120struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);108108-109109-static inline struct tipc_node *tipc_node_find(u32 addr)110110-{111111- if (likely(in_own_cluster(addr)))112112- return tipc_net.nodes[tipc_node(addr)];113113- return NULL;114114-}115121116122static inline void tipc_node_lock(struct tipc_node *n_ptr)117123{
+20-1
net/tipc/node_subscr.c
···22 * net/tipc/node_subscr.c: TIPC "node down" subscription handling33 *44 * Copyright (c) 1995-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···7575 tipc_node_lock(node_sub->node);7676 list_del_init(&node_sub->nodesub_list);7777 tipc_node_unlock(node_sub->node);7878+}7979+8080+/**8181+ * tipc_nodesub_notify - notify subscribers that a node is unreachable8282+ *8383+ * Note: node is locked by caller8484+ */8585+8686+void tipc_nodesub_notify(struct tipc_node *node)8787+{8888+ struct tipc_node_subscr *ns;8989+9090+ list_for_each_entry(ns, &node->nsub, nodesub_list) {9191+ if (ns->handle_node_down) {9292+ tipc_k_signal((Handler)ns->handle_node_down,9393+ (unsigned long)ns->usr_handle);9494+ ns->handle_node_down = NULL;9595+ }9696+ }7897}
+2-1
net/tipc/node_subscr.h
···22 * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling33 *44 * Copyright (c) 1995-2006, Ericsson AB55- * Copyright (c) 2005, Wind River Systems55+ * Copyright (c) 2005, 2010-2011, Wind River Systems66 * All rights reserved.77 *88 * Redistribution and use in source and binary forms, with or without···5959void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,6060 void *usr_handle, net_ev_handler handle_down);6161void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);6262+void tipc_nodesub_notify(struct tipc_node *node);62636364#endif
+32-38
net/tipc/socket.c
···5858#define tipc_sk(sk) ((struct tipc_sock *)(sk))5959#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))60606161+#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \6262+ (sock->state == SS_DISCONNECTING))6363+6164static int backlog_rcv(struct sock *sk, struct sk_buff *skb);6265static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);6366static void wakeupdispatch(struct tipc_port *tport);···292289 if (buf == NULL)293290 break;294291 atomic_dec(&tipc_queue_size);295295- if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))292292+ if (TIPC_SKB_CB(buf)->handle != 0)296293 buf_discard(buf);297294 else {298295 if ((sock->state == SS_CONNECTING) ||···914911 struct tipc_port *tport = tipc_sk_port(sk);915912 struct sk_buff *buf;916913 struct tipc_msg *msg;914914+ long timeout;917915 unsigned int sz;918916 u32 err;919917 int res;920918921919 /* Catch invalid receive requests */922922-923923- if (m->msg_iovlen != 1)924924- return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */925920926921 if (unlikely(!buf_len))927922 return -EINVAL;···931930 goto exit;932931 }933932933933+ timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);934934restart:935935936936 /* Look for a message in receive queue; wait if necessary */···941939 res = -ENOTCONN;942940 goto exit;943941 }944944- if (flags & MSG_DONTWAIT) {945945- res = -EWOULDBLOCK;942942+ if (timeout <= 0L) {943943+ res = timeout ? timeout : -EWOULDBLOCK;946944 goto exit;947945 }948946 release_sock(sk);949949- res = wait_event_interruptible(*sk_sleep(sk),950950- (!skb_queue_empty(&sk->sk_receive_queue) ||951951- (sock->state == SS_DISCONNECTING)));947947+ timeout = wait_event_interruptible_timeout(*sk_sleep(sk),948948+ tipc_rx_ready(sock),949949+ timeout);952950 lock_sock(sk);953953- if (res)954954- goto exit;955951 }956952957953 /* Look at first message in receive queue */···991991 sz = buf_len;992992 m->msg_flags |= MSG_TRUNC;993993 }994994- if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),995995- sz))) {996996- res = -EFAULT;994994+ res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),995995+ m->msg_iov, sz);996996+ if (res)997997 goto exit;998998- }999998 res = sz;1000999 } else {10011000 if ((sock->state == SS_READY) ||···10371038 struct tipc_port *tport = tipc_sk_port(sk);10381039 struct sk_buff *buf;10391040 struct tipc_msg *msg;10411041+ long timeout;10401042 unsigned int sz;10411043 int sz_to_copy, target, needed;10421044 int sz_copied = 0;10431043- char __user *crs = m->msg_iov->iov_base;10441044- unsigned char *buf_crs;10451045 u32 err;10461046 int res = 0;1047104710481048 /* Catch invalid receive attempts */10491049-10501050- if (m->msg_iovlen != 1)10511051- return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */1052104910531050 if (unlikely(!buf_len))10541051 return -EINVAL;···10581063 }1059106410601065 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);10611061-10661066+ timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);10621067restart:1063106810641069 /* Look for a message in receive queue; wait if necessary */···10681073 res = -ENOTCONN;10691074 goto exit;10701075 }10711071- if (flags & MSG_DONTWAIT) {10721072- res = -EWOULDBLOCK;10761076+ if (timeout <= 0L) {10771077+ res = timeout ? timeout : -EWOULDBLOCK;10731078 goto exit;10741079 }10751080 release_sock(sk);10761076- res = wait_event_interruptible(*sk_sleep(sk),10771077- (!skb_queue_empty(&sk->sk_receive_queue) ||10781078- (sock->state == SS_DISCONNECTING)));10811081+ timeout = wait_event_interruptible_timeout(*sk_sleep(sk),10821082+ tipc_rx_ready(sock),10831083+ timeout);10791084 lock_sock(sk);10801080- if (res)10811081- goto exit;10821085 }1083108610841087 /* Look at first message in receive queue */···11051112 /* Capture message data (if valid) & compute return value (always) */1106111311071114 if (!err) {11081108- buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);11091109- sz = (unsigned char *)msg + msg_size(msg) - buf_crs;11151115+ u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);1110111611171117+ sz -= offset;11111118 needed = (buf_len - sz_copied);11121119 sz_to_copy = (sz <= needed) ? sz : needed;11131113- if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {11141114- res = -EFAULT;11201120+11211121+ res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,11221122+ m->msg_iov, sz_to_copy);11231123+ if (res)11151124 goto exit;11161116- }11251125+11171126 sz_copied += sz_to_copy;1118112711191128 if (sz_to_copy < sz) {11201129 if (!(flags & MSG_PEEK))11211121- TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;11301130+ TIPC_SKB_CB(buf)->handle =11311131+ (void *)(unsigned long)(offset + sz_to_copy);11221132 goto exit;11231133 }11241124-11251125- crs += sz_to_copy;11261134 } else {11271135 if (sz_copied != 0)11281136 goto exit; /* can't add error msg to valid data */···1250125612511257 /* Enqueue message (finally!) */1252125812531253- TIPC_SKB_CB(buf)->handle = msg_data(msg);12591259+ TIPC_SKB_CB(buf)->handle = 0;12541260 atomic_inc(&tipc_queue_size);12551261 __skb_queue_tail(&sk->sk_receive_queue, buf);12561262···16021608 buf = __skb_dequeue(&sk->sk_receive_queue);16031609 if (buf) {16041610 atomic_dec(&tipc_queue_size);16051605- if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {16111611+ if (TIPC_SKB_CB(buf)->handle != 0) {16061612 buf_discard(buf);16071613 goto restart;16081614 }