diff options
author | Richard Alpe <richard.alpe@ericsson.com> | 2016-08-18 04:33:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-19 02:36:07 -0400 |
commit | b34040227be7da760cc72ef3c807e0985e7f0f16 (patch) | |
tree | 19043619527b69595286b449bc132201de8ac08d /net/tipc | |
parent | 36a6503feddadbbad415fb3891e80f94c10a9b21 (diff) |
tipc: add peer removal functionality
Add TIPC_NL_PEER_REMOVE netlink command. This command can remove
an offline peer node from the internal data structures.
This will be supported by the tipc user space tool in iproute2.
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/net.h | 2 | ||||
-rw-r--r-- | net/tipc/netlink.c | 5 | ||||
-rw-r--r-- | net/tipc/node.c | 63 | ||||
-rw-r--r-- | net/tipc/node.h | 1 |
4 files changed, 71 insertions, 0 deletions
diff --git a/net/tipc/net.h b/net/tipc/net.h index 77a7a118911d..c7c254902873 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | #include <net/genetlink.h> | 40 | #include <net/genetlink.h> |
41 | 41 | ||
42 | extern const struct nla_policy tipc_nl_net_policy[]; | ||
43 | |||
42 | int tipc_net_start(struct net *net, u32 addr); | 44 | int tipc_net_start(struct net *net, u32 addr); |
43 | 45 | ||
44 | void tipc_net_stop(struct net *net); | 46 | void tipc_net_stop(struct net *net); |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index a84daec0afe9..2718de667828 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -238,6 +238,11 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
238 | .dumpit = tipc_nl_node_dump_monitor_peer, | 238 | .dumpit = tipc_nl_node_dump_monitor_peer, |
239 | .policy = tipc_nl_policy, | 239 | .policy = tipc_nl_policy, |
240 | }, | 240 | }, |
241 | { | ||
242 | .cmd = TIPC_NL_PEER_REMOVE, | ||
243 | .doit = tipc_nl_peer_rm, | ||
244 | .policy = tipc_nl_policy, | ||
245 | } | ||
241 | }; | 246 | }; |
242 | 247 | ||
243 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) | 248 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 21974191e425..7e8b75fd1a02 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -1553,6 +1553,69 @@ discard: | |||
1553 | kfree_skb(skb); | 1553 | kfree_skb(skb); |
1554 | } | 1554 | } |
1555 | 1555 | ||
1556 | int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info) | ||
1557 | { | ||
1558 | struct net *net = sock_net(skb->sk); | ||
1559 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1560 | struct nlattr *attrs[TIPC_NLA_NET_MAX + 1]; | ||
1561 | struct tipc_node *peer; | ||
1562 | u32 addr; | ||
1563 | int err; | ||
1564 | int i; | ||
1565 | |||
1566 | /* We identify the peer by its net */ | ||
1567 | if (!info->attrs[TIPC_NLA_NET]) | ||
1568 | return -EINVAL; | ||
1569 | |||
1570 | err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX, | ||
1571 | info->attrs[TIPC_NLA_NET], | ||
1572 | tipc_nl_net_policy); | ||
1573 | if (err) | ||
1574 | return err; | ||
1575 | |||
1576 | if (!attrs[TIPC_NLA_NET_ADDR]) | ||
1577 | return -EINVAL; | ||
1578 | |||
1579 | addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]); | ||
1580 | |||
1581 | if (in_own_node(net, addr)) | ||
1582 | return -ENOTSUPP; | ||
1583 | |||
1584 | spin_lock_bh(&tn->node_list_lock); | ||
1585 | peer = tipc_node_find(net, addr); | ||
1586 | if (!peer) { | ||
1587 | spin_unlock_bh(&tn->node_list_lock); | ||
1588 | return -ENXIO; | ||
1589 | } | ||
1590 | |||
1591 | tipc_node_write_lock(peer); | ||
1592 | if (peer->state != SELF_DOWN_PEER_DOWN && | ||
1593 | peer->state != SELF_DOWN_PEER_LEAVING) { | ||
1594 | tipc_node_write_unlock(peer); | ||
1595 | err = -EBUSY; | ||
1596 | goto err_out; | ||
1597 | } | ||
1598 | |||
1599 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1600 | struct tipc_link_entry *le = &peer->links[i]; | ||
1601 | |||
1602 | if (le->link) { | ||
1603 | kfree(le->link); | ||
1604 | le->link = NULL; | ||
1605 | peer->link_cnt--; | ||
1606 | } | ||
1607 | } | ||
1608 | tipc_node_write_unlock(peer); | ||
1609 | tipc_node_delete(peer); | ||
1610 | |||
1611 | err = 0; | ||
1612 | err_out: | ||
1613 | tipc_node_put(peer); | ||
1614 | spin_unlock_bh(&tn->node_list_lock); | ||
1615 | |||
1616 | return err; | ||
1617 | } | ||
1618 | |||
1556 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | 1619 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) |
1557 | { | 1620 | { |
1558 | int err; | 1621 | int err; |
diff --git a/net/tipc/node.h b/net/tipc/node.h index d69fdfcc0ec9..4578b34c7dca 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -77,6 +77,7 @@ int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb); | |||
77 | int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info); | 77 | int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info); |
78 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); | 78 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); |
79 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); | 79 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); |
80 | int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info); | ||
80 | 81 | ||
81 | int tipc_nl_node_set_monitor(struct sk_buff *skb, struct genl_info *info); | 82 | int tipc_nl_node_set_monitor(struct sk_buff *skb, struct genl_info *info); |
82 | int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info); | 83 | int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info); |