Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b99c6d5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tipc-cleanups-improvements'



Jon Maloy says:

====================
tipc: some cleanups and improvements

This series mostly contains cleanups and cosmetic code changes.
The only real functional change is in #4 and #5, where we change the
locking structure for nodes and links in order to permit full
concurrency between links working in parallel on different interfaces.
Since the groundwork for this has been done in previous commit series,
this change constitutes only the final, small step to achieve that goal.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 12ded5ca 1a90632d
Loading
Loading
Loading
Loading
+4 −122
Original line number Diff line number Diff line
@@ -332,131 +332,15 @@ void tipc_bcast_remove_peer(struct net *net, struct tipc_link *rcv_l)
		tipc_sk_rcv(net, inputq);
}

static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
				      struct tipc_stats *stats)
{
	int i;
	struct nlattr *nest;

	struct nla_map {
		__u32 key;
		__u32 val;
	};

	struct nla_map map[] = {
		{TIPC_NLA_STATS_RX_INFO, stats->recv_info},
		{TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
		{TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
		{TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
		{TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
		{TIPC_NLA_STATS_TX_INFO, stats->sent_info},
		{TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
		{TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
		{TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
		{TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled},
		{TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks},
		{TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv},
		{TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks},
		{TIPC_NLA_STATS_TX_ACKS, stats->sent_acks},
		{TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted},
		{TIPC_NLA_STATS_DUPLICATES, stats->duplicates},
		{TIPC_NLA_STATS_LINK_CONGS, stats->link_congs},
		{TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz},
		{TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ?
			(stats->accu_queue_sz / stats->queue_sz_counts) : 0}
	};

	nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
	if (!nest)
		return -EMSGSIZE;

	for (i = 0; i <  ARRAY_SIZE(map); i++)
		if (nla_put_u32(skb, map[i].key, map[i].val))
			goto msg_full;

	nla_nest_end(skb, nest);

	return 0;
msg_full:
	nla_nest_cancel(skb, nest);

	return -EMSGSIZE;
}

int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
{
	int err;
	void *hdr;
	struct nlattr *attrs;
	struct nlattr *prop;
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_link *bcl = tn->bcl;

	if (!bcl)
		return 0;

	tipc_bcast_lock(net);

	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
			  NLM_F_MULTI, TIPC_NL_LINK_GET);
	if (!hdr)
		return -EMSGSIZE;

	attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
	if (!attrs)
		goto msg_full;

	/* The broadcast link is always up */
	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
		goto attr_msg_full;

	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST))
		goto attr_msg_full;
	if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
		goto attr_msg_full;
	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt))
		goto attr_msg_full;
	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt))
		goto attr_msg_full;

	prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
	if (!prop)
		goto attr_msg_full;
	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
		goto prop_msg_full;
	nla_nest_end(msg->skb, prop);

	err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats);
	if (err)
		goto attr_msg_full;

	tipc_bcast_unlock(net);
	nla_nest_end(msg->skb, attrs);
	genlmsg_end(msg->skb, hdr);

	return 0;

prop_msg_full:
	nla_nest_cancel(msg->skb, prop);
attr_msg_full:
	nla_nest_cancel(msg->skb, attrs);
msg_full:
	tipc_bcast_unlock(net);
	genlmsg_cancel(msg->skb, hdr);

	return -EMSGSIZE;
}

int tipc_bclink_reset_stats(struct net *net)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_link *bcl = tn->bcl;
	struct tipc_link *l = tipc_bc_sndlink(net);

	if (!bcl)
	if (!l)
		return -ENOPROTOOPT;

	tipc_bcast_lock(net);
	memset(&bcl->stats, 0, sizeof(bcl->stats));
	tipc_link_reset_stats(l);
	tipc_bcast_unlock(net);
	return 0;
}
@@ -530,9 +414,7 @@ int tipc_bcast_init(struct net *net)

void tipc_bcast_reinit(struct net *net)
{
	struct tipc_bc_base *b = tipc_bc_base(net);

	msg_set_prevnode(b->link->pmsg, tipc_own_addr(net));
	tipc_link_reinit(tipc_bc_sndlink(net), tipc_own_addr(net));
}

void tipc_bcast_stop(struct net *net)
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ struct tipc_node;
struct tipc_msg;
struct tipc_nl_msg;
struct tipc_node_map;
extern const char tipc_bclink_name[];

int tipc_bcast_init(struct net *net);
void tipc_bcast_reinit(struct net *net);
+70 −70
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
	[TIPC_NLA_MEDIA_PROP]		= { .type = NLA_NESTED }
};

static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr);
static void bearer_disable(struct net *net, struct tipc_bearer *b);

/**
 * tipc_media_find - locates specified media object by name
@@ -107,13 +107,13 @@ static struct tipc_media *media_find_id(u8 type)
void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
{
	char addr_str[MAX_ADDR_STR];
	struct tipc_media *m_ptr;
	struct tipc_media *m;
	int ret;

	m_ptr = media_find_id(a->media_id);
	m = media_find_id(a->media_id);

	if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
		ret = scnprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
	if (m && !m->addr2str(a, addr_str, sizeof(addr_str)))
		ret = scnprintf(buf, len, "%s(%s)", m->name, addr_str);
	else {
		u32 i;

@@ -175,13 +175,13 @@ static int bearer_name_validate(const char *name,
struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;
	u32 i;

	for (i = 0; i < MAX_BEARERS; i++) {
		b_ptr = rtnl_dereference(tn->bearer_list[i]);
		if (b_ptr && (!strcmp(b_ptr->name, name)))
			return b_ptr;
		b = rtnl_dereference(tn->bearer_list[i]);
		if (b && (!strcmp(b->name, name)))
			return b;
	}
	return NULL;
}
@@ -189,24 +189,24 @@ struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name)
void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;

	rcu_read_lock();
	b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (b_ptr)
		tipc_disc_add_dest(b_ptr->link_req);
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (b)
		tipc_disc_add_dest(b->link_req);
	rcu_read_unlock();
}

void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;

	rcu_read_lock();
	b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (b_ptr)
		tipc_disc_remove_dest(b_ptr->link_req);
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (b)
		tipc_disc_remove_dest(b->link_req);
	rcu_read_unlock();
}

@@ -218,8 +218,8 @@ static int tipc_enable_bearer(struct net *net, const char *name,
			      struct nlattr *attr[])
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_bearer *b_ptr;
	struct tipc_media *m_ptr;
	struct tipc_bearer *b;
	struct tipc_media *m;
	struct tipc_bearer_names b_names;
	char addr_string[16];
	u32 bearer_id;
@@ -255,31 +255,31 @@ static int tipc_enable_bearer(struct net *net, const char *name,
		return -EINVAL;
	}

	m_ptr = tipc_media_find(b_names.media_name);
	if (!m_ptr) {
	m = tipc_media_find(b_names.media_name);
	if (!m) {
		pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
			name, b_names.media_name);
		return -EINVAL;
	}

	if (priority == TIPC_MEDIA_LINK_PRI)
		priority = m_ptr->priority;
		priority = m->priority;

restart:
	bearer_id = MAX_BEARERS;
	with_this_prio = 1;
	for (i = MAX_BEARERS; i-- != 0; ) {
		b_ptr = rtnl_dereference(tn->bearer_list[i]);
		if (!b_ptr) {
		b = rtnl_dereference(tn->bearer_list[i]);
		if (!b) {
			bearer_id = i;
			continue;
		}
		if (!strcmp(name, b_ptr->name)) {
		if (!strcmp(name, b->name)) {
			pr_warn("Bearer <%s> rejected, already enabled\n",
				name);
			return -EINVAL;
		}
		if ((b_ptr->priority == priority) &&
		if ((b->priority == priority) &&
		    (++with_this_prio > 2)) {
			if (priority-- == 0) {
				pr_warn("Bearer <%s> rejected, duplicate priority\n",
@@ -297,35 +297,35 @@ static int tipc_enable_bearer(struct net *net, const char *name,
		return -EINVAL;
	}

	b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
	if (!b_ptr)
	b = kzalloc(sizeof(*b), GFP_ATOMIC);
	if (!b)
		return -ENOMEM;

	strcpy(b_ptr->name, name);
	b_ptr->media = m_ptr;
	res = m_ptr->enable_media(net, b_ptr, attr);
	strcpy(b->name, name);
	b->media = m;
	res = m->enable_media(net, b, attr);
	if (res) {
		pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
			name, -res);
		return -EINVAL;
	}

	b_ptr->identity = bearer_id;
	b_ptr->tolerance = m_ptr->tolerance;
	b_ptr->window = m_ptr->window;
	b_ptr->domain = disc_domain;
	b_ptr->net_plane = bearer_id + 'A';
	b_ptr->priority = priority;
	b->identity = bearer_id;
	b->tolerance = m->tolerance;
	b->window = m->window;
	b->domain = disc_domain;
	b->net_plane = bearer_id + 'A';
	b->priority = priority;

	res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr);
	res = tipc_disc_create(net, b, &b->bcast_addr);
	if (res) {
		bearer_disable(net, b_ptr);
		bearer_disable(net, b);
		pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
			name);
		return -EINVAL;
	}

	rcu_assign_pointer(tn->bearer_list[bearer_id], b_ptr);
	rcu_assign_pointer(tn->bearer_list[bearer_id], b);

	pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
		name,
@@ -336,11 +336,11 @@ static int tipc_enable_bearer(struct net *net, const char *name,
/**
 * tipc_reset_bearer - Reset all links established over this bearer
 */
static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr)
static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
{
	pr_info("Resetting bearer <%s>\n", b_ptr->name);
	tipc_node_delete_links(net, b_ptr->identity);
	tipc_disc_reset(net, b_ptr);
	pr_info("Resetting bearer <%s>\n", b->name);
	tipc_node_delete_links(net, b->identity);
	tipc_disc_reset(net, b);
	return 0;
}

@@ -349,26 +349,26 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr)
 *
 * Note: This routine assumes caller holds RTNL lock.
 */
static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr)
static void bearer_disable(struct net *net, struct tipc_bearer *b)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	u32 i;

	pr_info("Disabling bearer <%s>\n", b_ptr->name);
	b_ptr->media->disable_media(b_ptr);
	pr_info("Disabling bearer <%s>\n", b->name);
	b->media->disable_media(b);

	tipc_node_delete_links(net, b_ptr->identity);
	RCU_INIT_POINTER(b_ptr->media_ptr, NULL);
	if (b_ptr->link_req)
		tipc_disc_delete(b_ptr->link_req);
	tipc_node_delete_links(net, b->identity);
	RCU_INIT_POINTER(b->media_ptr, NULL);
	if (b->link_req)
		tipc_disc_delete(b->link_req);

	for (i = 0; i < MAX_BEARERS; i++) {
		if (b_ptr == rtnl_dereference(tn->bearer_list[i])) {
		if (b == rtnl_dereference(tn->bearer_list[i])) {
			RCU_INIT_POINTER(tn->bearer_list[i], NULL);
			break;
		}
	}
	kfree_rcu(b_ptr, rcu);
	kfree_rcu(b, rcu);
}

int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
@@ -411,7 +411,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b)
/**
 * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
 * @buf: the packet to be sent
 * @b_ptr: the bearer through which the packet is to be sent
 * @b: the bearer through which the packet is to be sent
 * @dest: peer destination address
 */
int tipc_l2_send_msg(struct net *net, struct sk_buff *skb,
@@ -532,14 +532,14 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
			   struct packet_type *pt, struct net_device *orig_dev)
{
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;

	rcu_read_lock();
	b_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
	if (likely(b_ptr)) {
	b = rcu_dereference_rtnl(dev->tipc_ptr);
	if (likely(b)) {
		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
			buf->next = NULL;
			tipc_rcv(dev_net(dev), buf, b_ptr);
			tipc_rcv(dev_net(dev), buf, b);
			rcu_read_unlock();
			return NET_RX_SUCCESS;
		}
@@ -564,13 +564,13 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct net *net = dev_net(dev);
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;

	b_ptr = rtnl_dereference(dev->tipc_ptr);
	if (!b_ptr)
	b = rtnl_dereference(dev->tipc_ptr);
	if (!b)
		return NOTIFY_DONE;

	b_ptr->mtu = dev->mtu;
	b->mtu = dev->mtu;

	switch (evt) {
	case NETDEV_CHANGE:
@@ -578,16 +578,16 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
			break;
	case NETDEV_GOING_DOWN:
	case NETDEV_CHANGEMTU:
		tipc_reset_bearer(net, b_ptr);
		tipc_reset_bearer(net, b);
		break;
	case NETDEV_CHANGEADDR:
		b_ptr->media->raw2addr(b_ptr, &b_ptr->addr,
		b->media->raw2addr(b, &b->addr,
				       (char *)dev->dev_addr);
		tipc_reset_bearer(net, b_ptr);
		tipc_reset_bearer(net, b);
		break;
	case NETDEV_UNREGISTER:
	case NETDEV_CHANGENAME:
		bearer_disable(dev_net(dev), b_ptr);
		bearer_disable(dev_net(dev), b);
		break;
	}
	return NOTIFY_OK;
@@ -623,13 +623,13 @@ void tipc_bearer_cleanup(void)
void tipc_bearer_stop(struct net *net)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_bearer *b_ptr;
	struct tipc_bearer *b;
	u32 i;

	for (i = 0; i < MAX_BEARERS; i++) {
		b_ptr = rtnl_dereference(tn->bearer_list[i]);
		if (b_ptr) {
			bearer_disable(net, b_ptr);
		b = rtnl_dereference(tn->bearer_list[i]);
		if (b) {
			bearer_disable(net, b);
			tn->bearer_list[i] = NULL;
		}
	}
+4 −4
Original line number Diff line number Diff line
@@ -103,11 +103,11 @@ struct tipc_bearer;
 */
struct tipc_media {
	int (*send_msg)(struct net *net, struct sk_buff *buf,
			struct tipc_bearer *b_ptr,
			struct tipc_bearer *b,
			struct tipc_media_addr *dest);
	int (*enable_media)(struct net *net, struct tipc_bearer *b_ptr,
	int (*enable_media)(struct net *net, struct tipc_bearer *b,
			    struct nlattr *attr[]);
	void (*disable_media)(struct tipc_bearer *b_ptr);
	void (*disable_media)(struct tipc_bearer *b);
	int (*addr2str)(struct tipc_media_addr *addr,
			char *strbuf,
			int bufsz);
@@ -176,7 +176,7 @@ struct tipc_bearer_names {
 * TIPC routines available to supported media types
 */

void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr);
void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b);

/*
 * Routines made available to TIPC by supported media types
+5 −0
Original line number Diff line number Diff line
@@ -118,6 +118,11 @@ static inline int tipc_netid(struct net *net)
	return tipc_net(net)->net_id;
}

static inline struct list_head *tipc_nodes(struct net *net)
{
	return &tipc_net(net)->node_list;
}

static inline u16 mod(u16 x)
{
	return x & 0xffffu;
Loading