Commit 6851cf28 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc-slim-down-name-table'

Jon Maloy says:

====================
tipc: slim down name table

We clean up and improve the name binding table:

 - Replace the memory consuming 'sub_sequence/service range' array with
   an RB tree.
 - Introduce support for overlapping service sequences/ranges

 v2: #1: Fixed a missing initialization reported by David Miller
     #4: Obsoleted and replaced a few more macros to get a consistent
         terminology in the API.
     #5: Added new commit to fix a potential string overflow bug (it
         is still only in net-next) reported by Arnd Bergmann
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 24197ee2 7494cfa6
...@@ -45,33 +45,33 @@ ...@@ -45,33 +45,33 @@
* TIPC addressing primitives * TIPC addressing primitives
*/ */
struct tipc_portid { struct tipc_socket_addr {
__u32 ref; __u32 ref;
__u32 node; __u32 node;
}; };
struct tipc_name { struct tipc_service_addr {
__u32 type; __u32 type;
__u32 instance; __u32 instance;
}; };
struct tipc_name_seq { struct tipc_service_range {
__u32 type; __u32 type;
__u32 lower; __u32 lower;
__u32 upper; __u32 upper;
}; };
/* /*
* Application-accessible port name types * Application-accessible service types
*/ */
#define TIPC_CFG_SRV 0 /* configuration service name type */ #define TIPC_NODE_STATE 0 /* node state service type */
#define TIPC_TOP_SRV 1 /* topology service name type */ #define TIPC_TOP_SRV 1 /* topology server service type */
#define TIPC_LINK_STATE 2 /* link state name type */ #define TIPC_LINK_STATE 2 /* link state service type */
#define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ #define TIPC_RESERVED_TYPES 64 /* lowest user-allowed service type */
/* /*
* Publication scopes when binding port names and port name sequences * Publication scopes when binding service / service range
*/ */
enum tipc_scope { enum tipc_scope {
TIPC_CLUSTER_SCOPE = 2, /* 0 can also be used */ TIPC_CLUSTER_SCOPE = 2, /* 0 can also be used */
...@@ -108,28 +108,28 @@ enum tipc_scope { ...@@ -108,28 +108,28 @@ enum tipc_scope {
* TIPC topology subscription service definitions * TIPC topology subscription service definitions
*/ */
#define TIPC_SUB_PORTS 0x01 /* filter for port availability */ #define TIPC_SUB_PORTS 0x01 /* filter: evt at each match */
#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ #define TIPC_SUB_SERVICE 0x02 /* filter: evt at first up/last down */
#define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */ #define TIPC_SUB_CANCEL 0x04 /* filter: cancel a subscription */
#define TIPC_WAIT_FOREVER (~0) /* timeout for permanent subscription */ #define TIPC_WAIT_FOREVER (~0) /* timeout for permanent subscription */
struct tipc_subscr { struct tipc_subscr {
struct tipc_name_seq seq; /* name sequence of interest */ struct tipc_service_range seq; /* range of interest */
__u32 timeout; /* subscription duration (in ms) */ __u32 timeout; /* subscription duration (in ms) */
__u32 filter; /* bitmask of filter options */ __u32 filter; /* bitmask of filter options */
char usr_handle[8]; /* available for subscriber use */ char usr_handle[8]; /* available for subscriber use */
}; };
#define TIPC_PUBLISHED 1 /* publication event */ #define TIPC_PUBLISHED 1 /* publication event */
#define TIPC_WITHDRAWN 2 /* withdraw event */ #define TIPC_WITHDRAWN 2 /* withdrawal event */
#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */
struct tipc_event { struct tipc_event {
__u32 event; /* event type */ __u32 event; /* event type */
__u32 found_lower; /* matching name seq instances */ __u32 found_lower; /* matching range */
__u32 found_upper; /* " " " " */ __u32 found_upper; /* " " */
struct tipc_portid port; /* associated port */ struct tipc_socket_addr port; /* associated socket */
struct tipc_subscr s; /* associated subscription */ struct tipc_subscr s; /* associated subscription */
}; };
...@@ -149,20 +149,20 @@ struct tipc_event { ...@@ -149,20 +149,20 @@ struct tipc_event {
#define SOL_TIPC 271 #define SOL_TIPC 271
#endif #endif
#define TIPC_ADDR_NAMESEQ 1 #define TIPC_ADDR_MCAST 1
#define TIPC_ADDR_MCAST 1 #define TIPC_SERVICE_RANGE 1
#define TIPC_ADDR_NAME 2 #define TIPC_SERVICE_ADDR 2
#define TIPC_ADDR_ID 3 #define TIPC_SOCKET_ADDR 3
struct sockaddr_tipc { struct sockaddr_tipc {
unsigned short family; unsigned short family;
unsigned char addrtype; unsigned char addrtype;
signed char scope; signed char scope;
union { union {
struct tipc_portid id; struct tipc_socket_addr id;
struct tipc_name_seq nameseq; struct tipc_service_range nameseq;
struct { struct {
struct tipc_name name; struct tipc_service_addr name;
__u32 domain; __u32 domain;
} name; } name;
} addr; } addr;
...@@ -216,7 +216,7 @@ struct tipc_group_req { ...@@ -216,7 +216,7 @@ struct tipc_group_req {
#define TIPC_MAX_MEDIA_NAME 16 #define TIPC_MAX_MEDIA_NAME 16
#define TIPC_MAX_IF_NAME 16 #define TIPC_MAX_IF_NAME 16
#define TIPC_MAX_BEARER_NAME 32 #define TIPC_MAX_BEARER_NAME 32
#define TIPC_MAX_LINK_NAME 60 #define TIPC_MAX_LINK_NAME 68
#define SIOCGETLINKNAME SIOCPROTOPRIVATE #define SIOCGETLINKNAME SIOCPROTOPRIVATE
...@@ -230,8 +230,13 @@ struct tipc_sioc_ln_req { ...@@ -230,8 +230,13 @@ struct tipc_sioc_ln_req {
/* The macros and functions below are deprecated: /* The macros and functions below are deprecated:
*/ */
#define TIPC_CFG_SRV 0
#define TIPC_ZONE_SCOPE 1 #define TIPC_ZONE_SCOPE 1
#define TIPC_ADDR_NAMESEQ 1
#define TIPC_ADDR_NAME 2
#define TIPC_ADDR_ID 3
#define TIPC_NODE_BITS 12 #define TIPC_NODE_BITS 12
#define TIPC_CLUSTER_BITS 12 #define TIPC_CLUSTER_BITS 12
#define TIPC_ZONE_BITS 8 #define TIPC_ZONE_BITS 8
...@@ -250,6 +255,10 @@ struct tipc_sioc_ln_req { ...@@ -250,6 +255,10 @@ struct tipc_sioc_ln_req {
#define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK) #define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK)
#define tipc_portid tipc_socket_addr
#define tipc_name tipc_service_addr
#define tipc_name_seq tipc_service_range
static inline __u32 tipc_addr(unsigned int zone, static inline __u32 tipc_addr(unsigned int zone,
unsigned int cluster, unsigned int cluster,
unsigned int node) unsigned int node)
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <net/netns/generic.h> #include <net/netns/generic.h>
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <net/genetlink.h>
struct tipc_node; struct tipc_node;
struct tipc_bearer; struct tipc_bearer;
......
...@@ -462,7 +462,8 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id, ...@@ -462,7 +462,8 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
sprintf(peer_str, "%x", peer); sprintf(peer_str, "%x", peer);
} }
/* Peer i/f name will be completed by reset/activate message */ /* Peer i/f name will be completed by reset/activate message */
sprintf(l->name, "%s:%s-%s:unknown", self_str, if_name, peer_str); snprintf(l->name, sizeof(l->name), "%s:%s-%s:unknown",
self_str, if_name, peer_str);
strcpy(l->if_name, if_name); strcpy(l->if_name, if_name);
l->addr = peer; l->addr = peer;
...@@ -1810,7 +1811,7 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, ...@@ -1810,7 +1811,7 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
{ {
int max_bulk = TIPC_MAX_PUBLICATIONS / (l->mtu / ITEM_SIZE); int max_bulk = TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE);
l->window = win; l->window = win;
l->backlog[TIPC_LOW_IMPORTANCE].limit = max_t(u16, 50, win); l->backlog[TIPC_LOW_IMPORTANCE].limit = max_t(u16, 50, win);
......
...@@ -204,12 +204,12 @@ void tipc_named_node_up(struct net *net, u32 dnode) ...@@ -204,12 +204,12 @@ void tipc_named_node_up(struct net *net, u32 dnode)
*/ */
static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr)
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = tipc_net(net);
struct publication *p; struct publication *p;
spin_lock_bh(&tn->nametbl_lock); spin_lock_bh(&tn->nametbl_lock);
p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, publ->upper,
publ->node, publ->port, publ->key); publ->node, publ->key);
if (p) if (p)
tipc_node_unsubscribe(net, &p->binding_node, addr); tipc_node_unsubscribe(net, &p->binding_node, addr);
spin_unlock_bh(&tn->nametbl_lock); spin_unlock_bh(&tn->nametbl_lock);
...@@ -261,81 +261,37 @@ void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr) ...@@ -261,81 +261,37 @@ void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr)
static bool tipc_update_nametbl(struct net *net, struct distr_item *i, static bool tipc_update_nametbl(struct net *net, struct distr_item *i,
u32 node, u32 dtype) u32 node, u32 dtype)
{ {
struct publication *publ = NULL; struct publication *p = NULL;
u32 lower = ntohl(i->lower);
u32 upper = ntohl(i->upper);
u32 type = ntohl(i->type);
u32 port = ntohl(i->port);
u32 key = ntohl(i->key);
if (dtype == PUBLICATION) { if (dtype == PUBLICATION) {
publ = tipc_nametbl_insert_publ(net, ntohl(i->type), p = tipc_nametbl_insert_publ(net, type, lower, upper,
ntohl(i->lower), TIPC_CLUSTER_SCOPE, node,
ntohl(i->upper), port, key);
TIPC_CLUSTER_SCOPE, node, if (p) {
ntohl(i->port), ntohl(i->key)); tipc_node_subscribe(net, &p->binding_node, node);
if (publ) {
tipc_node_subscribe(net, &publ->binding_node, node);
return true; return true;
} }
} else if (dtype == WITHDRAWAL) { } else if (dtype == WITHDRAWAL) {
publ = tipc_nametbl_remove_publ(net, ntohl(i->type), p = tipc_nametbl_remove_publ(net, type, lower,
ntohl(i->lower), upper, node, key);
node, ntohl(i->port), if (p) {
ntohl(i->key)); tipc_node_unsubscribe(net, &p->binding_node, node);
if (publ) { kfree_rcu(p, rcu);
tipc_node_unsubscribe(net, &publ->binding_node, node);
kfree_rcu(publ, rcu);
return true; return true;
} }
pr_warn_ratelimited("Failed to remove binding %u,%u from %x\n",
type, lower, node);
} else { } else {
pr_warn("Unrecognized name table message received\n"); pr_warn("Unrecognized name table message received\n");
} }
return false; return false;
} }
/**
* tipc_named_add_backlog - add a failed name table update to the backlog
*
*/
static void tipc_named_add_backlog(struct net *net, struct distr_item *i,
u32 type, u32 node)
{
struct distr_queue_item *e;
struct tipc_net *tn = net_generic(net, tipc_net_id);
unsigned long now = get_jiffies_64();
e = kzalloc(sizeof(*e), GFP_ATOMIC);
if (!e)
return;
e->dtype = type;
e->node = node;
e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout);
memcpy(e, i, sizeof(*i));
list_add_tail(&e->next, &tn->dist_queue);
}
/**
* tipc_named_process_backlog - try to process any pending name table updates
* from the network.
*/
void tipc_named_process_backlog(struct net *net)
{
struct distr_queue_item *e, *tmp;
struct tipc_net *tn = net_generic(net, tipc_net_id);
unsigned long now = get_jiffies_64();
list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) {
if (time_after(e->expires, now)) {
if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype))
continue;
} else {
pr_warn_ratelimited("Dropping name table update (%d) of {%u, %u, %u} from %x key=%u\n",
e->dtype, ntohl(e->i.type),
ntohl(e->i.lower),
ntohl(e->i.upper),
e->node, ntohl(e->i.key));
}
list_del(&e->next);
kfree(e);
}
}
/** /**
* tipc_named_rcv - process name table update messages sent by another node * tipc_named_rcv - process name table update messages sent by another node
*/ */
...@@ -358,12 +314,10 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) ...@@ -358,12 +314,10 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq)
count = msg_data_sz(msg) / ITEM_SIZE; count = msg_data_sz(msg) / ITEM_SIZE;
node = msg_orignode(msg); node = msg_orignode(msg);
while (count--) { while (count--) {
if (!tipc_update_nametbl(net, item, node, mtype)) tipc_update_nametbl(net, item, node, mtype);
tipc_named_add_backlog(net, item, mtype, node);
item++; item++;
} }
kfree_skb(skb); kfree_skb(skb);
tipc_named_process_backlog(net);
} }
spin_unlock_bh(&tn->nametbl_lock); spin_unlock_bh(&tn->nametbl_lock);
} }
......
...@@ -72,7 +72,6 @@ struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ); ...@@ -72,7 +72,6 @@ struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ);
void tipc_named_node_up(struct net *net, u32 dnode); void tipc_named_node_up(struct net *net, u32 dnode);
void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue);
void tipc_named_reinit(struct net *net); void tipc_named_reinit(struct net *net);
void tipc_named_process_backlog(struct net *net);
void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr); void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr);
#endif #endif
This diff is collapsed.
...@@ -97,7 +97,7 @@ struct publication { ...@@ -97,7 +97,7 @@ struct publication {
* @local_publ_count: number of publications issued by this node * @local_publ_count: number of publications issued by this node
*/ */
struct name_table { struct name_table {
struct hlist_head seq_hlist[TIPC_NAMETBL_SIZE]; struct hlist_head services[TIPC_NAMETBL_SIZE];
struct list_head node_scope; struct list_head node_scope;
struct list_head cluster_scope; struct list_head cluster_scope;
u32 local_publ_count; u32 local_publ_count;
...@@ -116,16 +116,16 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, ...@@ -116,16 +116,16 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
struct list_head *dsts, int *dstcnt, u32 exclude, struct list_head *dsts, int *dstcnt, u32 exclude,
bool all); bool all);
struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
u32 upper, u32 scope, u32 port_ref, u32 upper, u32 scope, u32 port,
u32 key); u32 key);
int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 upper,
u32 key); u32 key);
struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,
u32 lower, u32 upper, u32 scope, u32 lower, u32 upper, u32 scope,
u32 node, u32 ref, u32 key); u32 node, u32 ref, u32 key);
struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
u32 lower, u32 node, u32 ref, u32 lower, u32 upper,
u32 key); u32 node, u32 key);
void tipc_nametbl_subscribe(struct tipc_subscription *s); void tipc_nametbl_subscribe(struct tipc_subscription *s);
void tipc_nametbl_unsubscribe(struct tipc_subscription *s); void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
int tipc_nametbl_init(struct net *net); int tipc_nametbl_init(struct net *net);
......
...@@ -136,7 +136,7 @@ void tipc_net_stop(struct net *net) ...@@ -136,7 +136,7 @@ void tipc_net_stop(struct net *net)
if (!self) if (!self)
return; return;
tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, 0, self); tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, self, self);
rtnl_lock(); rtnl_lock();
tipc_bearer_stop(net); tipc_bearer_stop(net);
tipc_node_stop(net); tipc_node_stop(net);
......
...@@ -324,12 +324,12 @@ static void tipc_node_write_unlock(struct tipc_node *n) ...@@ -324,12 +324,12 @@ static void tipc_node_write_unlock(struct tipc_node *n)
if (flags & TIPC_NOTIFY_LINK_UP) { if (flags & TIPC_NOTIFY_LINK_UP) {
tipc_mon_peer_up(net, addr, bearer_id); tipc_mon_peer_up(net, addr, bearer_id);
tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr,
TIPC_NODE_SCOPE, link_id, addr); TIPC_NODE_SCOPE, link_id, link_id);
} }
if (flags & TIPC_NOTIFY_LINK_DOWN) { if (flags & TIPC_NOTIFY_LINK_DOWN) {
tipc_mon_peer_down(net, addr, bearer_id); tipc_mon_peer_down(net, addr, bearer_id);
tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr,
link_id, addr); addr, link_id);
} }
} }
......
...@@ -2634,12 +2634,12 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, ...@@ -2634,12 +2634,12 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
if (publ->upper != seq->upper) if (publ->upper != seq->upper)
break; break;
tipc_nametbl_withdraw(net, publ->type, publ->lower, tipc_nametbl_withdraw(net, publ->type, publ->lower,
publ->port, publ->key); publ->upper, publ->key);
rc = 0; rc = 0;
break; break;
} }
tipc_nametbl_withdraw(net, publ->type, publ->lower, tipc_nametbl_withdraw(net, publ->type, publ->lower,
publ->port, publ->key); publ->upper, publ->key);
rc = 0; rc = 0;
} }
if (list_empty(&tsk->publications)) if (list_empty(&tsk->publications))
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include "topsrv.h" #include "topsrv.h"
#define TIPC_MAX_SUBSCR 65535 #define TIPC_MAX_SUBSCR 65535
#define TIPC_MAX_PUBLICATIONS 65535 #define TIPC_MAX_PUBL 65535
struct tipc_subscription; struct tipc_subscription;
struct tipc_conn; struct tipc_conn;
...@@ -58,7 +58,7 @@ struct tipc_subscription { ...@@ -58,7 +58,7 @@ struct tipc_subscription {
struct kref kref; struct kref kref;
struct net *net; struct net *net;
struct timer_list timer; struct timer_list timer;
struct list_head nameseq_list; struct list_head service_list;
struct list_head sub_list; struct list_head sub_list;
struct tipc_event evt; struct tipc_event evt;
int conid; int conid;
......
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