Commit 06b8db9c authored by David S. Miller's avatar David S. Miller
parents 9100eb01 9bbbc59d
...@@ -256,7 +256,7 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) ...@@ -256,7 +256,7 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
if (bcbuf_acks(crs) == 0) { if (bcbuf_acks(crs) == 0) {
bcl->first_out = next; bcl->first_out = next;
bcl->out_queue_size--; bcl->out_queue_size--;
buf_discard(crs); kfree_skb(crs);
released = 1; released = 1;
} }
crs = next; crs = next;
...@@ -330,7 +330,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent) ...@@ -330,7 +330,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent)
tipc_bearer_send(&bcbearer->bearer, buf, NULL); tipc_bearer_send(&bcbearer->bearer, buf, NULL);
bcl->stats.sent_nacks++; bcl->stats.sent_nacks++;
spin_unlock_bh(&bc_lock); spin_unlock_bh(&bc_lock);
buf_discard(buf); kfree_skb(buf);
n_ptr->bclink.oos_state++; n_ptr->bclink.oos_state++;
} }
...@@ -374,7 +374,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) ...@@ -374,7 +374,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
if (!bclink->bcast_nodes.count) { if (!bclink->bcast_nodes.count) {
res = msg_data_sz(buf_msg(buf)); res = msg_data_sz(buf_msg(buf));
buf_discard(buf); kfree_skb(buf);
goto exit; goto exit;
} }
...@@ -480,7 +480,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) ...@@ -480,7 +480,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
if (likely(msg_mcast(msg))) if (likely(msg_mcast(msg)))
tipc_port_recv_mcast(buf, NULL); tipc_port_recv_mcast(buf, NULL);
else else
buf_discard(buf); kfree_skb(buf);
} else if (msg_user(msg) == MSG_BUNDLER) { } else if (msg_user(msg) == MSG_BUNDLER) {
spin_lock_bh(&bc_lock); spin_lock_bh(&bc_lock);
bclink_accept_pkt(node, seqno); bclink_accept_pkt(node, seqno);
...@@ -513,7 +513,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) ...@@ -513,7 +513,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
bclink_accept_pkt(node, seqno); bclink_accept_pkt(node, seqno);
spin_unlock_bh(&bc_lock); spin_unlock_bh(&bc_lock);
tipc_node_unlock(node); tipc_node_unlock(node);
buf_discard(buf); kfree_skb(buf);
} }
buf = NULL; buf = NULL;
...@@ -569,7 +569,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) ...@@ -569,7 +569,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
unlock: unlock:
tipc_node_unlock(node); tipc_node_unlock(node);
exit: exit:
buf_discard(buf); kfree_skb(buf);
} }
u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
......
...@@ -435,7 +435,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -435,7 +435,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
u32 i; u32 i;
int res = -EINVAL; int res = -EINVAL;
if (tipc_mode != TIPC_NET_MODE) { if (!tipc_own_addr) {
warn("Bearer <%s> rejected, not supported in standalone mode\n", warn("Bearer <%s> rejected, not supported in standalone mode\n",
name); name);
return -ENOPROTOOPT; return -ENOPROTOOPT;
...@@ -456,8 +456,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -456,8 +456,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
warn("Bearer <%s> rejected, illegal discovery domain\n", name); warn("Bearer <%s> rejected, illegal discovery domain\n", name);
return -EINVAL; return -EINVAL;
} }
if ((priority < TIPC_MIN_LINK_PRI || if ((priority > TIPC_MAX_LINK_PRI) &&
priority > TIPC_MAX_LINK_PRI) &&
(priority != TIPC_MEDIA_LINK_PRI)) { (priority != TIPC_MEDIA_LINK_PRI)) {
warn("Bearer <%s> rejected, illegal priority\n", name); warn("Bearer <%s> rejected, illegal priority\n", name);
return -EINVAL; return -EINVAL;
......
...@@ -179,7 +179,7 @@ static struct sk_buff *cfg_set_own_addr(void) ...@@ -179,7 +179,7 @@ static struct sk_buff *cfg_set_own_addr(void)
if (!tipc_addr_node_valid(addr)) if (!tipc_addr_node_valid(addr))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (node address)"); " (node address)");
if (tipc_mode == TIPC_NET_MODE) if (tipc_own_addr)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change node address once assigned)"); " (cannot change node address once assigned)");
...@@ -218,7 +218,7 @@ static struct sk_buff *cfg_set_max_publications(void) ...@@ -218,7 +218,7 @@ static struct sk_buff *cfg_set_max_publications(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 1, 65535)) if (value < 1 || value > 65535)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max publications must be 1-65535)"); " (max publications must be 1-65535)");
tipc_max_publications = value; tipc_max_publications = value;
...@@ -233,7 +233,7 @@ static struct sk_buff *cfg_set_max_subscriptions(void) ...@@ -233,7 +233,7 @@ static struct sk_buff *cfg_set_max_subscriptions(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 1, 65535)) if (value < 1 || value > 65535)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max subscriptions must be 1-65535"); " (max subscriptions must be 1-65535");
tipc_max_subscriptions = value; tipc_max_subscriptions = value;
...@@ -249,14 +249,11 @@ static struct sk_buff *cfg_set_max_ports(void) ...@@ -249,14 +249,11 @@ static struct sk_buff *cfg_set_max_ports(void)
value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_max_ports) if (value == tipc_max_ports)
return tipc_cfg_reply_none(); return tipc_cfg_reply_none();
if (value != delimit(value, 127, 65535)) if (value < 127 || value > 65535)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max ports must be 127-65535)"); " (max ports must be 127-65535)");
if (tipc_mode != TIPC_NOT_RUNNING) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change max ports while TIPC is active)");
" (cannot change max ports while TIPC is active)");
tipc_max_ports = value;
return tipc_cfg_reply_none();
} }
static struct sk_buff *cfg_set_netid(void) static struct sk_buff *cfg_set_netid(void)
...@@ -268,10 +265,10 @@ static struct sk_buff *cfg_set_netid(void) ...@@ -268,10 +265,10 @@ static struct sk_buff *cfg_set_netid(void)
value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value == tipc_net_id) if (value == tipc_net_id)
return tipc_cfg_reply_none(); return tipc_cfg_reply_none();
if (value != delimit(value, 1, 9999)) if (value < 1 || value > 9999)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network id must be 1-9999)"); " (network id must be 1-9999)");
if (tipc_mode == TIPC_NET_MODE) if (tipc_own_addr)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change network id once TIPC has joined a network)"); " (cannot change network id once TIPC has joined a network)");
tipc_net_id = value; tipc_net_id = value;
...@@ -481,7 +478,7 @@ int tipc_cfg_init(void) ...@@ -481,7 +478,7 @@ int tipc_cfg_init(void)
seq.type = TIPC_CFG_SRV; seq.type = TIPC_CFG_SRV;
seq.lower = seq.upper = tipc_own_addr; seq.lower = seq.upper = tipc_own_addr;
res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq);
if (res) if (res)
goto failed; goto failed;
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
/* global variables used by multiple sub-systems within TIPC */ /* global variables used by multiple sub-systems within TIPC */
int tipc_mode = TIPC_NOT_RUNNING;
int tipc_random; int tipc_random;
const char tipc_alphabet[] = const char tipc_alphabet[] =
...@@ -125,11 +124,6 @@ int tipc_core_start_net(unsigned long addr) ...@@ -125,11 +124,6 @@ int tipc_core_start_net(unsigned long addr)
static void tipc_core_stop(void) static void tipc_core_stop(void)
{ {
if (tipc_mode != TIPC_NODE_MODE)
return;
tipc_mode = TIPC_NOT_RUNNING;
tipc_netlink_stop(); tipc_netlink_stop();
tipc_handler_stop(); tipc_handler_stop();
tipc_cfg_stop(); tipc_cfg_stop();
...@@ -148,11 +142,7 @@ static int tipc_core_start(void) ...@@ -148,11 +142,7 @@ static int tipc_core_start(void)
{ {
int res; int res;
if (tipc_mode != TIPC_NOT_RUNNING)
return -ENOPROTOOPT;
get_random_bytes(&tipc_random, sizeof(tipc_random)); get_random_bytes(&tipc_random, sizeof(tipc_random));
tipc_mode = TIPC_NODE_MODE;
res = tipc_handler_start(); res = tipc_handler_start();
if (!res) if (!res)
......
...@@ -129,13 +129,6 @@ void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *); ...@@ -129,13 +129,6 @@ void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *);
#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */
/*
* TIPC operating mode routines
*/
#define TIPC_NOT_RUNNING 0
#define TIPC_NODE_MODE 1
#define TIPC_NET_MODE 2
/* /*
* Global configuration variables * Global configuration variables
*/ */
...@@ -151,7 +144,6 @@ extern int tipc_remote_management; ...@@ -151,7 +144,6 @@ extern int tipc_remote_management;
* Other global variables * Other global variables
*/ */
extern int tipc_mode;
extern int tipc_random; extern int tipc_random;
extern const char tipc_alphabet[]; extern const char tipc_alphabet[];
...@@ -168,16 +160,6 @@ extern void tipc_netlink_stop(void); ...@@ -168,16 +160,6 @@ extern void tipc_netlink_stop(void);
extern int tipc_socket_init(void); extern int tipc_socket_init(void);
extern void tipc_socket_stop(void); extern void tipc_socket_stop(void);
static inline int delimit(int val, int min, int max)
{
if (val > max)
return max;
if (val < min)
return min;
return val;
}
/* /*
* TIPC timer and signal code * TIPC timer and signal code
*/ */
...@@ -279,28 +261,4 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb) ...@@ -279,28 +261,4 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
extern struct sk_buff *tipc_buf_acquire(u32 size); extern struct sk_buff *tipc_buf_acquire(u32 size);
/**
* buf_discard - frees a TIPC message buffer
* @skb: message buffer
*
* Frees a message buffer. If passed NULL, just returns.
*/
static inline void buf_discard(struct sk_buff *skb)
{
kfree_skb(skb);
}
/**
* buf_linearize - convert a TIPC message buffer into a single contiguous piece
* @skb: message buffer
*
* Returns 0 on success.
*/
static inline int buf_linearize(struct sk_buff *skb)
{
return skb_linearize(skb);
}
#endif #endif
...@@ -82,6 +82,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, ...@@ -82,6 +82,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
msg = buf_msg(buf); msg = buf_msg(buf);
tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain);
msg_set_non_seq(msg, 1); msg_set_non_seq(msg, 1);
msg_set_node_sig(msg, tipc_random);
msg_set_dest_domain(msg, dest_domain); msg_set_dest_domain(msg, dest_domain);
msg_set_bc_netid(msg, tipc_net_id); msg_set_bc_netid(msg, tipc_net_id);
b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg)); b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg));
...@@ -121,20 +122,22 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) ...@@ -121,20 +122,22 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
{ {
struct tipc_node *n_ptr; struct tipc_node *n_ptr;
struct tipc_link *link; struct tipc_link *link;
struct tipc_media_addr media_addr, *addr; struct tipc_media_addr media_addr;
struct sk_buff *rbuf; struct sk_buff *rbuf;
struct tipc_msg *msg = buf_msg(buf); struct tipc_msg *msg = buf_msg(buf);
u32 dest = msg_dest_domain(msg); u32 dest = msg_dest_domain(msg);
u32 orig = msg_prevnode(msg); u32 orig = msg_prevnode(msg);
u32 net_id = msg_bc_netid(msg); u32 net_id = msg_bc_netid(msg);
u32 type = msg_type(msg); u32 type = msg_type(msg);
u32 signature = msg_node_sig(msg);
int addr_mismatch;
int link_fully_up; int link_fully_up;
media_addr.broadcast = 1; media_addr.broadcast = 1;
b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg));
buf_discard(buf); kfree_skb(buf);
/* Validate discovery message from requesting node */ /* Ensure message from node is valid and communication is permitted */
if (net_id != tipc_net_id) if (net_id != tipc_net_id)
return; return;
if (media_addr.broadcast) if (media_addr.broadcast)
...@@ -162,15 +165,50 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) ...@@ -162,15 +165,50 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
} }
tipc_node_lock(n_ptr); tipc_node_lock(n_ptr);
/* Prepare to validate requesting node's signature and media address */
link = n_ptr->links[b_ptr->identity]; link = n_ptr->links[b_ptr->identity];
addr_mismatch = (link != NULL) &&
memcmp(&link->media_addr, &media_addr, sizeof(media_addr));
/* Create a link endpoint for this bearer, if necessary */ /*
if (!link) { * Ensure discovery message's signature is correct
link = tipc_link_create(n_ptr, b_ptr, &media_addr); *
if (!link) { * If signature is incorrect and there is no working link to the node,
* accept the new signature but invalidate all existing links to the
* node so they won't re-activate without a new discovery message.
*
* If signature is incorrect and the requested link to the node is
* working, accept the new signature. (This is an instance of delayed
* rediscovery, where a link endpoint was able to re-establish contact
* with its peer endpoint on a node that rebooted before receiving a
* discovery message from that node.)
*
* If signature is incorrect and there is a working link to the node
* that is not the requested link, reject the request (must be from
* a duplicate node).
*/
if (signature != n_ptr->signature) {
if (n_ptr->working_links == 0) {
struct tipc_link *curr_link;
int i;
for (i = 0; i < MAX_BEARERS; i++) {
curr_link = n_ptr->links[i];
if (curr_link) {
memset(&curr_link->media_addr, 0,
sizeof(media_addr));
tipc_link_reset(curr_link);
}
}
addr_mismatch = (link != NULL);
} else if (tipc_link_is_up(link) && !addr_mismatch) {
/* delayed rediscovery */
} else {
disc_dupl_alert(b_ptr, orig, &media_addr);
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
return; return;
} }
n_ptr->signature = signature;
} }
/* /*
...@@ -183,17 +221,26 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) ...@@ -183,17 +221,26 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
* the new media address and reset the link to ensure it starts up * the new media address and reset the link to ensure it starts up
* cleanly. * cleanly.
*/ */
addr = &link->media_addr;
if (memcmp(addr, &media_addr, sizeof(*addr))) { if (addr_mismatch) {
if (tipc_link_is_up(link) || (!link->started)) { if (tipc_link_is_up(link)) {
disc_dupl_alert(b_ptr, orig, &media_addr); disc_dupl_alert(b_ptr, orig, &media_addr);
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
return; return;
} else {
memcpy(&link->media_addr, &media_addr,
sizeof(media_addr));
tipc_link_reset(link);
}
}
/* Create a link endpoint for this bearer, if necessary */
if (!link) {
link = tipc_link_create(n_ptr, b_ptr, &media_addr);
if (!link) {
tipc_node_unlock(n_ptr);
return;
} }
warn("Resetting link <%s>, peer interface address changed\n",
link->name);
memcpy(addr, &media_addr, sizeof(*addr));
tipc_link_reset(link);
} }
/* Accept discovery message & send response, if necessary */ /* Accept discovery message & send response, if necessary */
...@@ -203,7 +250,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) ...@@ -203,7 +250,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
if (rbuf) { if (rbuf) {
b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
buf_discard(rbuf); kfree_skb(rbuf);
} }
} }
...@@ -349,7 +396,7 @@ void tipc_disc_delete(struct tipc_link_req *req) ...@@ -349,7 +396,7 @@ void tipc_disc_delete(struct tipc_link_req *req)
{ {
k_cancel_timer(&req->timer); k_cancel_timer(&req->timer);
k_term_timer(&req->timer); k_term_timer(&req->timer);
buf_discard(req->buf); kfree_skb(req->buf);
kfree(req); kfree(req);
} }
...@@ -484,7 +484,7 @@ static void link_release_outqueue(struct tipc_link *l_ptr) ...@@ -484,7 +484,7 @@ static void link_release_outqueue(struct tipc_link *l_ptr)
while (buf) { while (buf) {
next = buf->next; next = buf->next;
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
} }
l_ptr->first_out = NULL; l_ptr->first_out = NULL;
...@@ -503,7 +503,7 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr) ...@@ -503,7 +503,7 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr)
while (buf) { while (buf) {
next = buf->next; next = buf->next;
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
} }
l_ptr->defragm_buf = NULL; l_ptr->defragm_buf = NULL;
...@@ -522,20 +522,20 @@ void tipc_link_stop(struct tipc_link *l_ptr) ...@@ -522,20 +522,20 @@ void tipc_link_stop(struct tipc_link *l_ptr)
buf = l_ptr->oldest_deferred_in; buf = l_ptr->oldest_deferred_in;
while (buf) { while (buf) {
next = buf->next; next = buf->next;
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
} }
buf = l_ptr->first_out; buf = l_ptr->first_out;
while (buf) { while (buf) {
next = buf->next; next = buf->next;
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
} }
tipc_link_reset_fragments(l_ptr); tipc_link_reset_fragments(l_ptr);
buf_discard(l_ptr->proto_msg_queue); kfree_skb(l_ptr->proto_msg_queue);
l_ptr->proto_msg_queue = NULL; l_ptr->proto_msg_queue = NULL;
} }
...@@ -571,12 +571,12 @@ void tipc_link_reset(struct tipc_link *l_ptr) ...@@ -571,12 +571,12 @@ void tipc_link_reset(struct tipc_link *l_ptr)
/* Clean up all queues: */ /* Clean up all queues: */
link_release_outqueue(l_ptr); link_release_outqueue(l_ptr);
buf_discard(l_ptr->proto_msg_queue); kfree_skb(l_ptr->proto_msg_queue);
l_ptr->proto_msg_queue = NULL; l_ptr->proto_msg_queue = NULL;
buf = l_ptr->oldest_deferred_in; buf = l_ptr->oldest_deferred_in;
while (buf) { while (buf) {
struct sk_buff *next = buf->next; struct sk_buff *next = buf->next;
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
} }
if (!list_empty(&l_ptr->waiting_ports)) if (!list_empty(&l_ptr->waiting_ports))
...@@ -810,7 +810,7 @@ static int link_bundle_buf(struct tipc_link *l_ptr, ...@@ -810,7 +810,7 @@ static int link_bundle_buf(struct tipc_link *l_ptr,
skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size); skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size);
msg_set_size(bundler_msg, to_pos + size); msg_set_size(bundler_msg, to_pos + size);
msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1);
buf_discard(buf); kfree_skb(buf);
l_ptr->stats.sent_bundled++; l_ptr->stats.sent_bundled++;
return 1; return 1;
} }
...@@ -871,17 +871,15 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) ...@@ -871,17 +871,15 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
u32 queue_limit = l_ptr->queue_limit[imp]; u32 queue_limit = l_ptr->queue_limit[imp];
u32 max_packet = l_ptr->max_pkt; u32 max_packet = l_ptr->max_pkt;
msg_set_prevnode(msg, tipc_own_addr); /* If routed message */
/* Match msg importance against queue limits: */ /* Match msg importance against queue limits: */
if (unlikely(queue_size >= queue_limit)) { if (unlikely(queue_size >= queue_limit)) {
if (imp <= TIPC_CRITICAL_IMPORTANCE) { if (imp <= TIPC_CRITICAL_IMPORTANCE) {
link_schedule_port(l_ptr, msg_origport(msg), size); link_schedule_port(l_ptr, msg_origport(msg), size);
buf_discard(buf); kfree_skb(buf);
return -ELINKCONG; return -ELINKCONG;
} }
buf_discard(buf); kfree_skb(buf);
if (imp > CONN_MANAGER) { if (imp > CONN_MANAGER) {
warn("Resetting link <%s>, send queue full", l_ptr->name); warn("Resetting link <%s>, send queue full", l_ptr->name);
tipc_link_reset(l_ptr); tipc_link_reset(l_ptr);
...@@ -968,10 +966,10 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) ...@@ -968,10 +966,10 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
if (l_ptr) if (l_ptr)
res = tipc_link_send_buf(l_ptr, buf); res = tipc_link_send_buf(l_ptr, buf);
else else
buf_discard(buf); kfree_skb(buf);
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
} else { } else {
buf_discard(buf); kfree_skb(buf);
} }
read_unlock_bh(&tipc_net_lock); read_unlock_bh(&tipc_net_lock);
return res; return res;
...@@ -1018,7 +1016,7 @@ void tipc_link_send_names(struct list_head *message_list, u32 dest) ...@@ -1018,7 +1016,7 @@ void tipc_link_send_names(struct list_head *message_list, u32 dest)
list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) {
list_del((struct list_head *)buf); list_del((struct list_head *)buf);
buf_discard(buf); kfree_skb(buf);
} }
} }
...@@ -1262,7 +1260,7 @@ static int link_send_sections_long(struct tipc_port *sender, ...@@ -1262,7 +1260,7 @@ static int link_send_sections_long(struct tipc_port *sender,
error: error:
for (; buf_chain; buf_chain = buf) { for (; buf_chain; buf_chain = buf) {
buf = buf_chain->next; buf = buf_chain->next;
buf_discard(buf_chain); kfree_skb(buf_chain);
} }
return -EFAULT; return -EFAULT;
} }
...@@ -1316,7 +1314,7 @@ static int link_send_sections_long(struct tipc_port *sender, ...@@ -1316,7 +1314,7 @@ static int link_send_sections_long(struct tipc_port *sender,
tipc_node_unlock(node); tipc_node_unlock(node);
for (; buf_chain; buf_chain = buf) { for (; buf_chain; buf_chain = buf) {
buf = buf_chain->next; buf = buf_chain->next;
buf_discard(buf_chain); kfree_skb(buf_chain);
} }
goto again; goto again;
} }
...@@ -1324,7 +1322,7 @@ static int link_send_sections_long(struct tipc_port *sender, ...@@ -1324,7 +1322,7 @@ static int link_send_sections_long(struct tipc_port *sender,
reject: reject:
for (; buf_chain; buf_chain = buf) { for (; buf_chain; buf_chain = buf) {
buf = buf_chain->next; buf = buf_chain->next;
buf_discard(buf_chain); kfree_skb(buf_chain);
} }
return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
total_len, TIPC_ERR_NO_NODE); total_len, TIPC_ERR_NO_NODE);
...@@ -1390,7 +1388,7 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr) ...@@ -1390,7 +1388,7 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
l_ptr->unacked_window = 0; l_ptr->unacked_window = 0;
buf_discard(buf); kfree_skb(buf);
l_ptr->proto_msg_queue = NULL; l_ptr->proto_msg_queue = NULL;
return 0; return 0;
} else { } else {
...@@ -1679,7 +1677,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) ...@@ -1679,7 +1677,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
/* Ensure message data is a single contiguous unit */ /* Ensure message data is a single contiguous unit */
if (unlikely(buf_linearize(buf))) if (unlikely(skb_linearize(buf)))
goto cont; goto cont;
/* Handle arrival of a non-unicast link message */ /* Handle arrival of a non-unicast link message */
...@@ -1744,7 +1742,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) ...@@ -1744,7 +1742,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
less_eq(buf_seqno(crs), ackd)) { less_eq(buf_seqno(crs), ackd)) {
struct sk_buff *next = crs->next; struct sk_buff *next = crs->next;
buf_discard(crs); kfree_skb(crs);
crs = next; crs = next;
released++; released++;
} }
...@@ -1773,57 +1771,56 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) ...@@ -1773,57 +1771,56 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
if (unlikely(l_ptr->oldest_deferred_in)) if (unlikely(l_ptr->oldest_deferred_in))
head = link_insert_deferred_queue(l_ptr, head = link_insert_deferred_queue(l_ptr,
head); head);
if (likely(msg_is_dest(msg, tipc_own_addr))) {
int ret;
deliver: deliver:
if (likely(msg_isdata(msg))) { if (likely(msg_isdata(msg))) {
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
tipc_port_recv_msg(buf); tipc_port_recv_msg(buf);
continue; continue;
}
switch (msg_user(msg)) {
int ret;
case MSG_BUNDLER:
l_ptr->stats.recv_bundles++;
l_ptr->stats.recv_bundled +=
msg_msgcnt(msg);
tipc_node_unlock(n_ptr);
tipc_link_recv_bundle(buf);
continue;
case NAME_DISTRIBUTOR:
tipc_node_unlock(n_ptr);
tipc_named_recv(buf);
continue;
case CONN_MANAGER:
tipc_node_unlock(n_ptr);
tipc_port_recv_proto_msg(buf);
continue;
case MSG_FRAGMENTER:
l_ptr->stats.recv_fragments++;
ret = tipc_link_recv_fragment(
&l_ptr->defragm_buf,
&buf, &msg);
if (ret == 1) {
l_ptr->stats.recv_fragmented++;
goto deliver;
} }
switch (msg_user(msg)) { if (ret == -1)
case MSG_BUNDLER: l_ptr->next_in_no--;
l_ptr->stats.recv_bundles++; break;
l_ptr->stats.recv_bundled += case CHANGEOVER_PROTOCOL:
msg_msgcnt(msg); type = msg_type(msg);
tipc_node_unlock(n_ptr); if (link_recv_changeover_msg(&l_ptr,
tipc_link_recv_bundle(buf); &buf)) {
continue; msg = buf_msg(buf);
case NAME_DISTRIBUTOR: seq_no = msg_seqno(msg);
tipc_node_unlock(n_ptr); if (type == ORIGINAL_MSG)
tipc_named_recv(buf);
continue;
case CONN_MANAGER:
tipc_node_unlock(n_ptr);
tipc_port_recv_proto_msg(buf);
continue;
case MSG_FRAGMENTER:
l_ptr->stats.recv_fragments++;
ret = tipc_link_recv_fragment(
&l_ptr->defragm_buf,
&buf, &msg);
if (ret == 1) {
l_ptr->stats.recv_fragmented++;
goto deliver; goto deliver;
} goto protocol_check;
if (ret == -1)
l_ptr->next_in_no--;
break;
case CHANGEOVER_PROTOCOL:
type = msg_type(msg);
if (link_recv_changeover_msg(&l_ptr, &buf)) {
msg = buf_msg(buf);
seq_no = msg_seqno(msg);
if (type == ORIGINAL_MSG)
goto deliver;
goto protocol_check;
}
break;
default:
buf_discard(buf);
buf = NULL;
break;
} }
break;
default:
kfree_skb(buf);
buf = NULL;
break;
} }
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
tipc_net_route_msg(buf); tipc_net_route_msg(buf);
...@@ -1852,7 +1849,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) ...@@ -1852,7 +1849,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
} }
tipc_node_unlock(n_ptr); tipc_node_unlock(n_ptr);
cont: cont:
buf_discard(buf); kfree_skb(buf);
} }
read_unlock_bh(&tipc_net_lock); read_unlock_bh(&tipc_net_lock);
} }
...@@ -1892,7 +1889,7 @@ u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, ...@@ -1892,7 +1889,7 @@ u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
u32 curr_seqno = buf_seqno(queue_buf); u32 curr_seqno = buf_seqno(queue_buf);
if (seq_no == curr_seqno) { if (seq_no == curr_seqno) {
buf_discard(buf); kfree_skb(buf);
return 0; return 0;
} }
...@@ -1933,7 +1930,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, ...@@ -1933,7 +1930,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
if (less(seq_no, mod(l_ptr->next_in_no))) { if (less(seq_no, mod(l_ptr->next_in_no))) {
l_ptr->stats.duplicates++; l_ptr->stats.duplicates++;
buf_discard(buf); kfree_skb(buf);
return; return;
} }
...@@ -1962,7 +1959,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, ...@@ -1962,7 +1959,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
/* Discard any previous message that was deferred due to congestion */ /* Discard any previous message that was deferred due to congestion */
if (l_ptr->proto_msg_queue) { if (l_ptr->proto_msg_queue) {
buf_discard(l_ptr->proto_msg_queue); kfree_skb(l_ptr->proto_msg_queue);
l_ptr->proto_msg_queue = NULL; l_ptr->proto_msg_queue = NULL;
} }
...@@ -2061,7 +2058,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, ...@@ -2061,7 +2058,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
/* Discard message if it was sent successfully */ /* Discard message if it was sent successfully */
l_ptr->unacked_window = 0; l_ptr->unacked_window = 0;
buf_discard(buf); kfree_skb(buf);
} }
/* /*
...@@ -2205,7 +2202,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) ...@@ -2205,7 +2202,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
break; break;
} }
exit: exit:
buf_discard(buf); kfree_skb(buf);
} }
...@@ -2403,7 +2400,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, ...@@ -2403,7 +2400,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr,
warn("Link changeover error, duplicate msg dropped\n"); warn("Link changeover error, duplicate msg dropped\n");
goto exit; goto exit;
} }
buf_discard(tunnel_buf); kfree_skb(tunnel_buf);
return 1; return 1;
} }
...@@ -2435,7 +2432,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, ...@@ -2435,7 +2432,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr,
} else { } else {
*buf = buf_extract(tunnel_buf, INT_H_SIZE); *buf = buf_extract(tunnel_buf, INT_H_SIZE);
if (*buf != NULL) { if (*buf != NULL) {
buf_discard(tunnel_buf); kfree_skb(tunnel_buf);
return 1; return 1;
} else { } else {
warn("Link changeover error, original msg dropped\n"); warn("Link changeover error, original msg dropped\n");
...@@ -2443,7 +2440,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, ...@@ -2443,7 +2440,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr,
} }
exit: exit:
*buf = NULL; *buf = NULL;
buf_discard(tunnel_buf); kfree_skb(tunnel_buf);
return 0; return 0;
} }
...@@ -2465,7 +2462,7 @@ void tipc_link_recv_bundle(struct sk_buff *buf) ...@@ -2465,7 +2462,7 @@ void tipc_link_recv_bundle(struct sk_buff *buf)
pos += align(msg_size(buf_msg(obuf))); pos += align(msg_size(buf_msg(obuf)));
tipc_net_route_msg(obuf); tipc_net_route_msg(obuf);
} }
buf_discard(buf); kfree_skb(buf);
} }
/* /*
...@@ -2514,11 +2511,11 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) ...@@ -2514,11 +2511,11 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
} }
fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
if (fragm == NULL) { if (fragm == NULL) {
buf_discard(buf); kfree_skb(buf);
while (buf_chain) { while (buf_chain) {
buf = buf_chain; buf = buf_chain;
buf_chain = buf_chain->next; buf_chain = buf_chain->next;
buf_discard(buf); kfree_skb(buf);
} }
return -ENOMEM; return -ENOMEM;
} }
...@@ -2535,7 +2532,7 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) ...@@ -2535,7 +2532,7 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
crs += fragm_sz; crs += fragm_sz;
msg_set_type(&fragm_hdr, FRAGMENT); msg_set_type(&fragm_hdr, FRAGMENT);
} }
buf_discard(buf); kfree_skb(buf);
/* Append chain of fragments to send queue & send them */ /* Append chain of fragments to send queue & send them */
...@@ -2622,7 +2619,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, ...@@ -2622,7 +2619,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
if (msg_type(imsg) == TIPC_MCAST_MSG) if (msg_type(imsg) == TIPC_MCAST_MSG)
max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
if (msg_size(imsg) > max) { if (msg_size(imsg) > max) {
buf_discard(fbuf); kfree_skb(fbuf);
return 0; return 0;
} }
pbuf = tipc_buf_acquire(msg_size(imsg)); pbuf = tipc_buf_acquire(msg_size(imsg));
...@@ -2638,10 +2635,10 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, ...@@ -2638,10 +2635,10 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
set_expected_frags(pbuf, exp_fragm_cnt - 1); set_expected_frags(pbuf, exp_fragm_cnt - 1);
} else { } else {
dbg("Link unable to reassemble fragmented message\n"); dbg("Link unable to reassemble fragmented message\n");
buf_discard(fbuf); kfree_skb(fbuf);
return -1; return -1;
} }
buf_discard(fbuf); kfree_skb(fbuf);
return 0; return 0;
} else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) {
u32 dsz = msg_data_sz(fragm); u32 dsz = msg_data_sz(fragm);
...@@ -2650,7 +2647,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, ...@@ -2650,7 +2647,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
u32 exp_frags = get_expected_frags(pbuf) - 1; u32 exp_frags = get_expected_frags(pbuf) - 1;
skb_copy_to_linear_data_offset(pbuf, crs, skb_copy_to_linear_data_offset(pbuf, crs,
msg_data(fragm), dsz); msg_data(fragm), dsz);
buf_discard(fbuf); kfree_skb(fbuf);
/* Is message complete? */ /* Is message complete? */
...@@ -2667,7 +2664,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, ...@@ -2667,7 +2664,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
set_expected_frags(pbuf, exp_frags); set_expected_frags(pbuf, exp_frags);
return 0; return 0;
} }
buf_discard(fbuf); kfree_skb(fbuf);
return 0; return 0;
} }
...@@ -2698,7 +2695,7 @@ static void link_check_defragm_bufs(struct tipc_link *l_ptr) ...@@ -2698,7 +2695,7 @@ static void link_check_defragm_bufs(struct tipc_link *l_ptr)
prev->next = buf->next; prev->next = buf->next;
else else
l_ptr->defragm_buf = buf->next; l_ptr->defragm_buf = buf->next;
buf_discard(buf); kfree_skb(buf);
} }
buf = next; buf = next;
} }
...@@ -3073,7 +3070,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s ...@@ -3073,7 +3070,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s
str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
(char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
if (!str_len) { if (!str_len) {
buf_discard(buf); kfree_skb(buf);
return tipc_cfg_reply_error_string("link not found"); return tipc_cfg_reply_error_string("link not found");
} }
......
...@@ -304,7 +304,7 @@ struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space) ...@@ -304,7 +304,7 @@ struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
if (value != delimit(value, 0, 32768)) if (value > 32768)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (log size must be 0-32768)"); " (log size must be 0-32768)");
if (tipc_log_resize(value)) if (tipc_log_resize(value))
......
...@@ -106,7 +106,7 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, ...@@ -106,7 +106,7 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
if (likely(res)) if (likely(res))
return dsz; return dsz;
buf_discard(*buf); kfree_skb(*buf);
*buf = NULL; *buf = NULL;
return -EFAULT; return -EFAULT;
} }
......
...@@ -384,11 +384,6 @@ static inline void msg_set_destnode(struct tipc_msg *m, u32 a) ...@@ -384,11 +384,6 @@ static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
msg_set_word(m, 7, a); msg_set_word(m, 7, a);
} }
static inline int msg_is_dest(struct tipc_msg *m, u32 d)
{
return msg_short(m) || (msg_destnode(m) == d);
}
static inline u32 msg_nametype(struct tipc_msg *m) static inline u32 msg_nametype(struct tipc_msg *m)
{ {
return msg_word(m, 8); return msg_word(m, 8);
...@@ -517,6 +512,16 @@ static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) ...@@ -517,6 +512,16 @@ static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
msg_set_bits(m, 1, 16, 0x1fff, n); msg_set_bits(m, 1, 16, 0x1fff, n);
} }
static inline u32 msg_node_sig(struct tipc_msg *m)
{
return msg_bits(m, 1, 0, 0xffff);
}
static inline void msg_set_node_sig(struct tipc_msg *m, u32 n)
{
msg_set_bits(m, 1, 0, 0xffff, n);
}
/* /*
* Word 2 * Word 2
......
...@@ -120,7 +120,7 @@ static void named_cluster_distribute(struct sk_buff *buf) ...@@ -120,7 +120,7 @@ static void named_cluster_distribute(struct sk_buff *buf)
} }
} }
buf_discard(buf); kfree_skb(buf);
} }
/** /**
...@@ -312,7 +312,7 @@ void tipc_named_recv(struct sk_buff *buf) ...@@ -312,7 +312,7 @@ void tipc_named_recv(struct sk_buff *buf)
item++; item++;
} }
write_unlock_bh(&tipc_nametbl_lock); write_unlock_bh(&tipc_nametbl_lock);
buf_discard(buf); kfree_skb(buf);
} }
/** /**
......
...@@ -114,10 +114,8 @@ struct name_table { ...@@ -114,10 +114,8 @@ struct name_table {
}; };
static struct name_table table; static struct name_table table;
static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
DEFINE_RWLOCK(tipc_nametbl_lock); DEFINE_RWLOCK(tipc_nametbl_lock);
static int hash(int x) static int hash(int x)
{ {
return x & (tipc_nametbl_size - 1); return x & (tipc_nametbl_size - 1);
...@@ -270,6 +268,13 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, ...@@ -270,6 +268,13 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
} }
info = sseq->info; info = sseq->info;
/* Check if an identical publication already exists */
list_for_each_entry(publ, &info->zone_list, zone_list) {
if ((publ->ref == port) && (publ->key == key) &&
(!publ->node || (publ->node == node)))
return NULL;
}
} else { } else {
u32 inspos; u32 inspos;
struct sub_seq *freesseq; struct sub_seq *freesseq;
...@@ -534,10 +539,17 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, ...@@ -534,10 +539,17 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
} }
/* /*
* tipc_nametbl_translate - translate name to port id * tipc_nametbl_translate - perform name translation
*
* On entry, 'destnode' is the search domain used during translation.
* *
* Note: on entry 'destnode' is the search domain used during translation; * On exit:
* on exit it passes back the node address of the matching port (if any) * - if name translation is deferred to another node/cluster/zone,
* leaves 'destnode' unchanged (will be non-zero) and returns 0
* - if name translation is attempted and succeeds, sets 'destnode'
* to publishing node and returns port reference (will be non-zero)
* - if name translation is attempted and fails, sets 'destnode' to 0
* and returns 0
*/ */
u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
...@@ -547,6 +559,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) ...@@ -547,6 +559,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
struct publication *publ; struct publication *publ;
struct name_seq *seq; struct name_seq *seq;
u32 ref = 0; u32 ref = 0;
u32 node = 0;
if (!tipc_in_scope(*destnode, tipc_own_addr)) if (!tipc_in_scope(*destnode, tipc_own_addr))
return 0; return 0;
...@@ -604,11 +617,12 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) ...@@ -604,11 +617,12 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
} }
ref = publ->ref; ref = publ->ref;
*destnode = publ->node; node = publ->node;
no_match: no_match:
spin_unlock_bh(&seq->lock); spin_unlock_bh(&seq->lock);
not_found: not_found:
read_unlock_bh(&tipc_nametbl_lock); read_unlock_bh(&tipc_nametbl_lock);
*destnode = node;
return ref; return ref;
} }
...@@ -665,22 +679,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, ...@@ -665,22 +679,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
return res; return res;
} }
/** /*
* tipc_nametbl_publish_rsv - publish port name using a reserved name type
*/
int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
struct tipc_name_seq const *seq)
{
int res;
atomic_inc(&rsv_publ_ok);
res = tipc_publish(ref, scope, seq);
atomic_dec(&rsv_publ_ok);
return res;
}
/**
* tipc_nametbl_publish - add name publication to network name tables * tipc_nametbl_publish - add name publication to network name tables
*/ */
...@@ -694,11 +693,6 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, ...@@ -694,11 +693,6 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
tipc_max_publications); tipc_max_publications);
return NULL; return NULL;
} }
if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
warn("Publication failed, reserved name {%u,%u,%u}\n",
type, lower, upper);
return NULL;
}
write_lock_bh(&tipc_nametbl_lock); write_lock_bh(&tipc_nametbl_lock);
table.local_publ_count++; table.local_publ_count++;
......
...@@ -91,8 +91,6 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); ...@@ -91,8 +91,6 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
struct tipc_port_list *dports); struct tipc_port_list *dports);
int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
struct tipc_name_seq const *seq);
struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
u32 scope, u32 port_ref, u32 key); u32 scope, u32 port_ref, u32 key);
int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
......
...@@ -117,7 +117,7 @@ static void net_route_named_msg(struct sk_buff *buf) ...@@ -117,7 +117,7 @@ static void net_route_named_msg(struct sk_buff *buf)
u32 dport; u32 dport;
if (!msg_named(msg)) { if (!msg_named(msg)) {
buf_discard(buf); kfree_skb(buf);
return; return;
} }
...@@ -161,7 +161,7 @@ void tipc_net_route_msg(struct sk_buff *buf) ...@@ -161,7 +161,7 @@ void tipc_net_route_msg(struct sk_buff *buf)
tipc_port_recv_proto_msg(buf); tipc_port_recv_proto_msg(buf);
break; break;
default: default:
buf_discard(buf); kfree_skb(buf);
} }
return; return;
} }
...@@ -175,14 +175,10 @@ int tipc_net_start(u32 addr) ...@@ -175,14 +175,10 @@ int tipc_net_start(u32 addr)
{ {
char addr_string[16]; char addr_string[16];
if (tipc_mode != TIPC_NODE_MODE)
return -ENOPROTOOPT;
tipc_subscr_stop(); tipc_subscr_stop();
tipc_cfg_stop(); tipc_cfg_stop();
tipc_own_addr = addr; tipc_own_addr = addr;
tipc_mode = TIPC_NET_MODE;
tipc_named_reinit(); tipc_named_reinit();
tipc_port_reinit(); tipc_port_reinit();
...@@ -201,10 +197,9 @@ void tipc_net_stop(void) ...@@ -201,10 +197,9 @@ void tipc_net_stop(void)
{ {
struct tipc_node *node, *t_node; struct tipc_node *node, *t_node;
if (tipc_mode != TIPC_NET_MODE) if (!tipc_own_addr)
return; return;
write_lock_bh(&tipc_net_lock); write_lock_bh(&tipc_net_lock);
tipc_mode = TIPC_NODE_MODE;
tipc_bearer_stop(); tipc_bearer_stop();
tipc_bclink_stop(); tipc_bclink_stop();
list_for_each_entry_safe(node, t_node, &tipc_node_list, list) list_for_each_entry_safe(node, t_node, &tipc_node_list, list)
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include "node.h" #include "node.h"
#include "name_distr.h" #include "name_distr.h"
#define NODE_HTABLE_SIZE 512
static void node_lost_contact(struct tipc_node *n_ptr); static void node_lost_contact(struct tipc_node *n_ptr);
static void node_established_contact(struct tipc_node *n_ptr); static void node_established_contact(struct tipc_node *n_ptr);
...@@ -50,6 +52,17 @@ static u32 tipc_num_nodes; ...@@ -50,6 +52,17 @@ static u32 tipc_num_nodes;
static atomic_t tipc_num_links = ATOMIC_INIT(0); static atomic_t tipc_num_links = ATOMIC_INIT(0);
/*
* A trivial power-of-two bitmask technique is used for speed, since this
* operation is done for every incoming TIPC packet. The number of hash table
* entries has been chosen so that no hash chain exceeds 8 nodes and will
* usually be much smaller (typically only a single node).
*/
static inline unsigned int tipc_hashfn(u32 addr)
{
return addr & (NODE_HTABLE_SIZE - 1);
}
/* /*
* tipc_node_find - locate specified node object, if it exists * tipc_node_find - locate specified node object, if it exists
*/ */
...@@ -112,6 +125,7 @@ struct tipc_node *tipc_node_create(u32 addr) ...@@ -112,6 +125,7 @@ struct tipc_node *tipc_node_create(u32 addr)
} }
list_add_tail(&n_ptr->list, &temp_node->list); list_add_tail(&n_ptr->list, &temp_node->list);
n_ptr->block_setup = WAIT_PEER_DOWN; n_ptr->block_setup = WAIT_PEER_DOWN;
n_ptr->signature = INVALID_NODE_SIG;
tipc_num_nodes++; tipc_num_nodes++;
...@@ -252,60 +266,12 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) ...@@ -252,60 +266,12 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
n_ptr->link_cnt--; n_ptr->link_cnt--;
} }
/*
* Routing table management - five cases to handle:
*
* 1: A link towards a zone/cluster external node comes up.
* => Send a multicast message updating routing tables of all
* system nodes within own cluster that the new destination
* can be reached via this node.
* (node.establishedContact()=>cluster.multicastNewRoute())
*
* 2: A link towards a slave node comes up.
* => Send a multicast message updating routing tables of all
* system nodes within own cluster that the new destination
* can be reached via this node.
* (node.establishedContact()=>cluster.multicastNewRoute())
* => Send a message to the slave node about existence
* of all system nodes within cluster:
* (node.establishedContact()=>cluster.sendLocalRoutes())
*
* 3: A new cluster local system node becomes available.
* => Send message(s) to this particular node containing
* information about all cluster external and slave
* nodes which can be reached via this node.
* (node.establishedContact()==>network.sendExternalRoutes())
* (node.establishedContact()==>network.sendSlaveRoutes())
* => Send messages to all directly connected slave nodes
* containing information about the existence of the new node
* (node.establishedContact()=>cluster.multicastNewRoute())
*
* 4: The link towards a zone/cluster external node or slave
* node goes down.
* => Send a multcast message updating routing tables of all
* nodes within cluster that the new destination can not any
* longer be reached via this node.
* (node.lostAllLinks()=>cluster.bcastLostRoute())
*
* 5: A cluster local system node becomes unavailable.
* => Remove all references to this node from the local
* routing tables. Note: This is a completely node
* local operation.
* (node.lostAllLinks()=>network.removeAsRouter())
* => Send messages to all directly connected slave nodes
* containing information about loss of the node
* (node.establishedContact()=>cluster.multicastLostRoute())
*
*/
static void node_established_contact(struct tipc_node *n_ptr) static void node_established_contact(struct tipc_node *n_ptr)
{ {
tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
/* Syncronize broadcast acks */
n_ptr->bclink.acked = tipc_bclink_get_last_sent();
if (n_ptr->bclink.supportable) { if (n_ptr->bclink.supportable) {
n_ptr->bclink.acked = tipc_bclink_get_last_sent();
tipc_bclink_add_node(n_ptr->addr); tipc_bclink_add_node(n_ptr->addr);
n_ptr->bclink.supported = 1; n_ptr->bclink.supported = 1;
} }
...@@ -339,12 +305,12 @@ static void node_lost_contact(struct tipc_node *n_ptr) ...@@ -339,12 +305,12 @@ static void node_lost_contact(struct tipc_node *n_ptr)
while (n_ptr->bclink.deferred_head) { while (n_ptr->bclink.deferred_head) {
struct sk_buff *buf = n_ptr->bclink.deferred_head; struct sk_buff *buf = n_ptr->bclink.deferred_head;
n_ptr->bclink.deferred_head = buf->next; n_ptr->bclink.deferred_head = buf->next;
buf_discard(buf); kfree_skb(buf);
} }
n_ptr->bclink.deferred_size = 0; n_ptr->bclink.deferred_size = 0;
if (n_ptr->bclink.defragm) { if (n_ptr->bclink.defragm) {
buf_discard(n_ptr->bclink.defragm); kfree_skb(n_ptr->bclink.defragm);
n_ptr->bclink.defragm = NULL; n_ptr->bclink.defragm = NULL;
} }
...@@ -440,7 +406,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) ...@@ -440,7 +406,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network address)"); " (network address)");
if (tipc_mode != TIPC_NET_MODE) if (!tipc_own_addr)
return tipc_cfg_reply_none(); return tipc_cfg_reply_none();
read_lock_bh(&tipc_net_lock); read_lock_bh(&tipc_net_lock);
......
...@@ -42,6 +42,11 @@ ...@@ -42,6 +42,11 @@
#include "net.h" #include "net.h"
#include "bearer.h" #include "bearer.h"
/*
* Out-of-range value for node signature
*/
#define INVALID_NODE_SIG 0x10000
/* Flags used to block (re)establishment of contact with a neighboring node */ /* Flags used to block (re)establishment of contact with a neighboring node */
#define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */ #define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */
...@@ -61,6 +66,7 @@ ...@@ -61,6 +66,7 @@
* @block_setup: bit mask of conditions preventing link establishment to node * @block_setup: bit mask of conditions preventing link establishment to node
* @link_cnt: number of links to node * @link_cnt: number of links to node
* @permit_changeover: non-zero if node has redundant links to this system * @permit_changeover: non-zero if node has redundant links to this system
* @signature: node instance identifier
* @bclink: broadcast-related info * @bclink: broadcast-related info
* @supportable: non-zero if node supports TIPC b'cast link capability * @supportable: non-zero if node supports TIPC b'cast link capability
* @supported: non-zero if node supports TIPC b'cast capability * @supported: non-zero if node supports TIPC b'cast capability
...@@ -86,6 +92,7 @@ struct tipc_node { ...@@ -86,6 +92,7 @@ struct tipc_node {
int working_links; int working_links;
int block_setup; int block_setup;
int permit_changeover; int permit_changeover;
u32 signature;
struct { struct {
u8 supportable; u8 supportable;
u8 supported; u8 supported;
...@@ -100,20 +107,8 @@ struct tipc_node { ...@@ -100,20 +107,8 @@ struct tipc_node {
} bclink; } bclink;
}; };
#define NODE_HTABLE_SIZE 512
extern struct list_head tipc_node_list; extern struct list_head tipc_node_list;
/*
* A trivial power-of-two bitmask technique is used for speed, since this
* operation is done for every incoming TIPC packet. The number of hash table
* entries has been chosen so that no hash chain exceeds 8 nodes and will
* usually be much smaller (typically only a single node).
*/
static inline unsigned int tipc_hashfn(u32 addr)
{
return addr & (NODE_HTABLE_SIZE - 1);
}
struct tipc_node *tipc_node_find(u32 addr); struct tipc_node *tipc_node_find(u32 addr);
struct tipc_node *tipc_node_create(u32 addr); struct tipc_node *tipc_node_create(u32 addr);
void tipc_node_delete(struct tipc_node *n_ptr); void tipc_node_delete(struct tipc_node *n_ptr);
......
...@@ -116,13 +116,13 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, ...@@ -116,13 +116,13 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
ibuf = skb_copy(buf, GFP_ATOMIC); ibuf = skb_copy(buf, GFP_ATOMIC);
if (ibuf == NULL) { if (ibuf == NULL) {
tipc_port_list_free(&dports); tipc_port_list_free(&dports);
buf_discard(buf); kfree_skb(buf);
return -ENOMEM; return -ENOMEM;
} }
} }
res = tipc_bclink_send_msg(buf); res = tipc_bclink_send_msg(buf);
if ((res < 0) && (dports.count != 0)) if ((res < 0) && (dports.count != 0))
buf_discard(ibuf); kfree_skb(ibuf);
} else { } else {
ibuf = buf; ibuf = buf;
} }
...@@ -187,7 +187,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) ...@@ -187,7 +187,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp)
} }
} }
exit: exit:
buf_discard(buf); kfree_skb(buf);
tipc_port_list_free(dp); tipc_port_list_free(dp);
} }
...@@ -420,7 +420,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) ...@@ -420,7 +420,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
else else
tipc_link_send(rbuf, src_node, msg_link_selector(rmsg)); tipc_link_send(rbuf, src_node, msg_link_selector(rmsg));
exit: exit:
buf_discard(buf); kfree_skb(buf);
return data_sz; return data_sz;
} }
...@@ -568,7 +568,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) ...@@ -568,7 +568,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
tipc_port_unlock(p_ptr); tipc_port_unlock(p_ptr);
exit: exit:
tipc_net_route_msg(r_buf); tipc_net_route_msg(r_buf);
buf_discard(buf); kfree_skb(buf);
} }
static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id)
...@@ -759,7 +759,7 @@ static void port_dispatcher_sigh(void *dummy) ...@@ -759,7 +759,7 @@ static void port_dispatcher_sigh(void *dummy)
} }
} }
if (buf) if (buf)
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
continue; continue;
err: err:
...@@ -813,7 +813,7 @@ static void port_dispatcher_sigh(void *dummy) ...@@ -813,7 +813,7 @@ static void port_dispatcher_sigh(void *dummy)
} }
} }
if (buf) if (buf)
buf_discard(buf); kfree_skb(buf);
buf = next; buf = next;
continue; continue;
reject: reject:
...@@ -1054,8 +1054,6 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) ...@@ -1054,8 +1054,6 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
msg = &p_ptr->phdr; msg = &p_ptr->phdr;
msg_set_destnode(msg, peer->node); msg_set_destnode(msg, peer->node);
msg_set_destport(msg, peer->ref); msg_set_destport(msg, peer->ref);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, p_ptr->ref);
msg_set_type(msg, TIPC_CONN_MSG); msg_set_type(msg, TIPC_CONN_MSG);
msg_set_lookup_scope(msg, 0); msg_set_lookup_scope(msg, 0);
msg_set_hdr_sz(msg, SHORT_H_SIZE); msg_set_hdr_sz(msg, SHORT_H_SIZE);
...@@ -1133,6 +1131,49 @@ int tipc_shutdown(u32 ref) ...@@ -1133,6 +1131,49 @@ int tipc_shutdown(u32 ref)
return tipc_disconnect(ref); return tipc_disconnect(ref);
} }
/**
* tipc_port_recv_msg - receive message from lower layer and deliver to port user
*/
int tipc_port_recv_msg(struct sk_buff *buf)
{
struct tipc_port *p_ptr;
struct tipc_msg *msg = buf_msg(buf);
u32 destport = msg_destport(msg);
u32 dsz = msg_data_sz(msg);
u32 err;
/* forward unresolved named message */
if (unlikely(!destport)) {
tipc_net_route_msg(buf);
return dsz;
}
/* validate destination & pass to port, otherwise reject message */
p_ptr = tipc_port_lock(destport);
if (likely(p_ptr)) {
if (likely(p_ptr->connected)) {
if ((unlikely(msg_origport(msg) !=
tipc_peer_port(p_ptr))) ||
(unlikely(msg_orignode(msg) !=
tipc_peer_node(p_ptr))) ||
(unlikely(!msg_connected(msg)))) {
err = TIPC_ERR_NO_PORT;
tipc_port_unlock(p_ptr);
goto reject;
}
}
err = p_ptr->dispatcher(p_ptr, buf);
tipc_port_unlock(p_ptr);
if (likely(!err))
return dsz;
} else {
err = TIPC_ERR_NO_PORT;
}
reject:
return tipc_reject_msg(buf, err);
}
/* /*
* tipc_port_recv_sections(): Concatenate and deliver sectioned * tipc_port_recv_sections(): Concatenate and deliver sectioned
* message for this node. * message for this node.
...@@ -1211,8 +1252,6 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, ...@@ -1211,8 +1252,6 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
msg = &p_ptr->phdr; msg = &p_ptr->phdr;
msg_set_type(msg, TIPC_NAMED_MSG); msg_set_type(msg, TIPC_NAMED_MSG);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, ref);
msg_set_hdr_sz(msg, NAMED_H_SIZE); msg_set_hdr_sz(msg, NAMED_H_SIZE);
msg_set_nametype(msg, name->type); msg_set_nametype(msg, name->type);
msg_set_nameinst(msg, name->instance); msg_set_nameinst(msg, name->instance);
...@@ -1221,7 +1260,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, ...@@ -1221,7 +1260,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
msg_set_destnode(msg, destnode); msg_set_destnode(msg, destnode);
msg_set_destport(msg, destport); msg_set_destport(msg, destport);
if (likely(destport)) { if (likely(destport || destnode)) {
if (likely(destnode == tipc_own_addr)) if (likely(destnode == tipc_own_addr))
res = tipc_port_recv_sections(p_ptr, num_sect, res = tipc_port_recv_sections(p_ptr, num_sect,
msg_sect, total_len); msg_sect, total_len);
...@@ -1262,8 +1301,6 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, ...@@ -1262,8 +1301,6 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
msg = &p_ptr->phdr; msg = &p_ptr->phdr;
msg_set_type(msg, TIPC_DIRECT_MSG); msg_set_type(msg, TIPC_DIRECT_MSG);
msg_set_lookup_scope(msg, 0); msg_set_lookup_scope(msg, 0);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node); msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref); msg_set_destport(msg, dest->ref);
msg_set_hdr_sz(msg, BASIC_H_SIZE); msg_set_hdr_sz(msg, BASIC_H_SIZE);
...@@ -1302,8 +1339,6 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, ...@@ -1302,8 +1339,6 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
msg = &p_ptr->phdr; msg = &p_ptr->phdr;
msg_set_type(msg, TIPC_DIRECT_MSG); msg_set_type(msg, TIPC_DIRECT_MSG);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node); msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref); msg_set_destport(msg, dest->ref);
msg_set_hdr_sz(msg, BASIC_H_SIZE); msg_set_hdr_sz(msg, BASIC_H_SIZE);
......
...@@ -205,6 +205,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr); ...@@ -205,6 +205,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr);
/* /*
* TIPC messaging routines * TIPC messaging routines
*/ */
int tipc_port_recv_msg(struct sk_buff *buf);
int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect,
unsigned int total_len); unsigned int total_len);
...@@ -271,45 +272,4 @@ static inline int tipc_port_congested(struct tipc_port *p_ptr) ...@@ -271,45 +272,4 @@ static inline int tipc_port_congested(struct tipc_port *p_ptr)
return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2);
} }
/**
* tipc_port_recv_msg - receive message from lower layer and deliver to port user
*/
static inline int tipc_port_recv_msg(struct sk_buff *buf)
{
struct tipc_port *p_ptr;
struct tipc_msg *msg = buf_msg(buf);
u32 destport = msg_destport(msg);
u32 dsz = msg_data_sz(msg);
u32 err;
/* forward unresolved named message */
if (unlikely(!destport)) {
tipc_net_route_msg(buf);
return dsz;
}
/* validate destination & pass to port, otherwise reject message */
p_ptr = tipc_port_lock(destport);
if (likely(p_ptr)) {
if (likely(p_ptr->connected)) {
if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) ||
(unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) ||
(unlikely(!msg_connected(msg)))) {
err = TIPC_ERR_NO_PORT;
tipc_port_unlock(p_ptr);
goto reject;
}
}
err = p_ptr->dispatcher(p_ptr, buf);
tipc_port_unlock(p_ptr);
if (likely(!err))
return dsz;
} else {
err = TIPC_ERR_NO_PORT;
}
reject:
return tipc_reject_msg(buf, err);
}
#endif #endif
...@@ -126,7 +126,7 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0); ...@@ -126,7 +126,7 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
static void advance_rx_queue(struct sock *sk) static void advance_rx_queue(struct sock *sk)
{ {
buf_discard(__skb_dequeue(&sk->sk_receive_queue)); kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
atomic_dec(&tipc_queue_size); atomic_dec(&tipc_queue_size);
} }
...@@ -142,7 +142,7 @@ static void discard_rx_queue(struct sock *sk) ...@@ -142,7 +142,7 @@ static void discard_rx_queue(struct sock *sk)
while ((buf = __skb_dequeue(&sk->sk_receive_queue))) { while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
atomic_dec(&tipc_queue_size); atomic_dec(&tipc_queue_size);
buf_discard(buf); kfree_skb(buf);
} }
} }
...@@ -288,7 +288,7 @@ static int release(struct socket *sock) ...@@ -288,7 +288,7 @@ static int release(struct socket *sock)
break; break;
atomic_dec(&tipc_queue_size); atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0) if (TIPC_SKB_CB(buf)->handle != 0)
buf_discard(buf); kfree_skb(buf);
else { else {
if ((sock->state == SS_CONNECTING) || if ((sock->state == SS_CONNECTING) ||
(sock->state == SS_CONNECTED)) { (sock->state == SS_CONNECTED)) {
...@@ -355,6 +355,9 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) ...@@ -355,6 +355,9 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
else if (addr->addrtype != TIPC_ADDR_NAMESEQ) else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
if (addr->addr.nameseq.type < TIPC_RESERVED_TYPES)
return -EACCES;
return (addr->scope > 0) ? return (addr->scope > 0) ?
tipc_publish(portref, addr->scope, &addr->addr.nameseq) : tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
...@@ -1612,7 +1615,7 @@ static int shutdown(struct socket *sock, int how) ...@@ -1612,7 +1615,7 @@ static int shutdown(struct socket *sock, int how)
if (buf) { if (buf) {
atomic_dec(&tipc_queue_size); atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0) { if (TIPC_SKB_CB(buf)->handle != 0) {
buf_discard(buf); kfree_skb(buf);
goto restart; goto restart;
} }
tipc_disconnect(tport->ref); tipc_disconnect(tport->ref);
......
...@@ -552,7 +552,7 @@ int tipc_subscr_start(void) ...@@ -552,7 +552,7 @@ int tipc_subscr_start(void)
if (res) if (res)
goto failed; goto failed;
res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); res = tipc_publish(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
if (res) { if (res) {
tipc_deleteport(topsrv.setup_port); tipc_deleteport(topsrv.setup_port);
topsrv.setup_port = 0; topsrv.setup_port = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment