/*
* net/tipc/discover.c
- *
+ *
* Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define CHECK_LINK_COUNT 306
#endif
-/*
+/*
* TODO: Most of the inter-cluster setup stuff should be
* rewritten, and be made conformant with specification.
- */
+ */
/**
#if 0
-int disc_create_link(const struct tipc_link_create *argv)
+int disc_create_link(const struct tipc_link_create *argv)
{
- /*
- * Code for inter cluster link setup here
+ /*
+ * Code for inter cluster link setup here
*/
return TIPC_OK;
}
* disc_lost_link(): A link has lost contact
*/
-void tipc_disc_link_event(u32 addr, char *name, int up)
+void tipc_disc_link_event(u32 addr, char *name, int up)
{
if (in_own_cluster(addr))
return;
- /*
- * Code for inter cluster link setup here
+ /*
+ * Code for inter cluster link setup here
*/
}
-/**
+/**
* tipc_disc_init_msg - initialize a link setup message
* @type: message type (request or response)
* @req_links: number of links associated with message
if (buf) {
msg = buf_msg(buf);
- msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE,
- dest_domain);
- msg_set_non_seq(msg);
+ msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain);
+ msg_set_non_seq(msg, 1);
msg_set_req_links(msg, req_links);
msg_set_dest_domain(msg, dest_domain);
msg_set_bc_netid(msg, tipc_net_id);
}
/**
+ * disc_dupl_alert - issue node address duplication alert
+ * @b_ptr: pointer to bearer detecting duplication
+ * @node_addr: duplicated node address
+ * @media_addr: media address advertised by duplicated node
+ */
+
+static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
+ struct tipc_media_addr *media_addr)
+{
+ char node_addr_str[16];
+ char media_addr_str[64];
+ struct print_buf pb;
+
+ addr_string_fill(node_addr_str, node_addr);
+ tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));
+ tipc_media_addr_printf(&pb, media_addr);
+ tipc_printbuf_validate(&pb);
+ warn("Duplicate %s using %s seen on <%s>\n",
+ node_addr_str, media_addr_str, b_ptr->publ.name);
+}
+
+/**
* tipc_disc_recv_msg - handle incoming link setup message (request or response)
* @buf: buffer containing message
+ * @b_ptr: bearer that message arrived on
*/
-void tipc_disc_recv_msg(struct sk_buff *buf)
+void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
{
- struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle;
struct link *link;
struct tipc_media_addr media_addr;
struct tipc_msg *msg = buf_msg(buf);
return;
if (!tipc_addr_node_valid(orig))
return;
- if (orig == tipc_own_addr)
+ if (orig == tipc_own_addr) {
+ if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
+ disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
return;
+ }
if (!in_scope(dest, tipc_own_addr))
return;
if (is_slave(tipc_own_addr) && is_slave(orig))
/* Always accept link here */
struct sk_buff *rbuf;
struct tipc_media_addr *addr;
- struct node *n_ptr = tipc_node_find(orig);
- int link_up;
+ struct tipc_node *n_ptr = tipc_node_find(orig);
+ int link_fully_up;
+
dbg(" in own cluster\n");
if (n_ptr == NULL) {
n_ptr = tipc_node_create(orig);
- }
- if (n_ptr == NULL) {
- warn("Memory squeeze; Failed to create node\n");
- return;
+ if (!n_ptr)
+ return;
}
spin_lock_bh(&n_ptr->lock);
link = n_ptr->links[b_ptr->identity];
dbg("creating link\n");
link = tipc_link_create(b_ptr, orig, &media_addr);
if (!link) {
- spin_unlock_bh(&n_ptr->lock);
+ spin_unlock_bh(&n_ptr->lock);
return;
}
}
addr = &link->media_addr;
if (memcmp(addr, &media_addr, sizeof(*addr))) {
- char addr_string[16];
-
- warn("New bearer address for %s\n",
- addr_string_fill(addr_string, orig));
+ if (tipc_link_is_up(link) || (!link->started)) {
+ disc_dupl_alert(b_ptr, orig, &media_addr);
+ spin_unlock_bh(&n_ptr->lock);
+ return;
+ }
+ warn("Resetting link <%s>, peer interface address changed\n",
+ link->name);
memcpy(addr, &media_addr, sizeof(*addr));
- tipc_link_reset(link);
+ tipc_link_reset(link);
}
- link_up = tipc_link_is_up(link);
- spin_unlock_bh(&n_ptr->lock);
- if ((type == DSC_RESP_MSG) || link_up)
+ link_fully_up = (link->state == WORKING_WORKING);
+ spin_unlock_bh(&n_ptr->lock);
+ if ((type == DSC_RESP_MSG) || link_fully_up)
return;
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
if (rbuf != NULL) {
* @req: ptr to link request structure
*/
-void tipc_disc_stop_link_req(struct link_req *req)
+void tipc_disc_stop_link_req(struct link_req *req)
{
if (!req)
return;
-
+
k_cancel_timer(&req->timer);
k_term_timer(&req->timer);
buf_discard(req->buf);
kfree(req);
-}
+}
/**
* tipc_disc_update_link_req - update frequency of periodic link setup requests
* @req: ptr to link request structure
*/
-void tipc_disc_update_link_req(struct link_req *req)
+void tipc_disc_update_link_req(struct link_req *req)
{
if (!req)
return;
} else {
/* leave timer "as is" if haven't yet reached a "normal" rate */
}
-}
+}
/**
* disc_timeout - send a periodic link setup request
* @req: ptr to link request structure
- *
+ *
* Called whenever a link setup request timer associated with a bearer expires.
*/
-static void disc_timeout(struct link_req *req)
+static void disc_timeout(struct link_req *req)
{
spin_lock_bh(&req->bearer->publ.lock);
/* leave timer interval "as is" if already at a "normal" rate */
} else {
req->timer_intv *= 2;
- if (req->timer_intv > TIPC_LINK_REQ_SLOW)
- req->timer_intv = TIPC_LINK_REQ_SLOW;
- if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
+ if (req->timer_intv > TIPC_LINK_REQ_FAST)
+ req->timer_intv = TIPC_LINK_REQ_FAST;
+ if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
(req->bearer->nodes.count))
req->timer_intv = TIPC_LINK_REQ_SLOW;
}
* @dest: destination address for request messages
* @dest_domain: network domain of node(s) which should respond to message
* @req_links: max number of desired links
- *
+ *
* Returns pointer to link request structure, or NULL if unable to create.
*/
-struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
const struct tipc_media_addr *dest,
u32 dest_domain,
- u32 req_links)
+ u32 req_links)
{
struct link_req *req;
- req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC);
+ req = kmalloc(sizeof(*req), GFP_ATOMIC);
if (!req)
return NULL;
k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
k_start_timer(&req->timer, req->timer_intv);
return req;
-}
+}