aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-01-08 15:03:30 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-09 12:35:58 -0500
commit232d07b74a33b9f5d48516dc1d8ce41723ada593 (patch)
tree04a2df7d400b7aa4fbb0028d033bbace6e0ebdcc /net/tipc/socket.c
parent8348500f80d5660af29c475e1f15d412d83564c9 (diff)
tipc: improve groupcast scope handling
When a member joins a group, it also indicates a binding scope. This makes it possible to create both node local groups, invisible to other nodes, as well as cluster global groups, visible everywhere. In order to avoid that different members end up having permanently differing views of group size and memberhip, we must inhibit locally and globally bound members from joining the same group. We do this by using the binding scope as an additional separator between groups. I.e., a member must ignore all membership events from sockets using a different scope than itself, and all lookups for message destinations must require an exact match between the message's lookup scope and the potential target's binding scope. Apart from making it possible to create local groups using the same identity on different nodes, a side effect of this is that it now also becomes possible to create a cluster global group with the same identity across the same nodes, without interfering with the local groups. Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c88
1 files changed, 53 insertions, 35 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e3a02f1fcab5..b24dab3996c9 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -928,21 +928,22 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m,
928 struct list_head *cong_links = &tsk->cong_links; 928 struct list_head *cong_links = &tsk->cong_links;
929 int blks = tsk_blocks(GROUP_H_SIZE + dlen); 929 int blks = tsk_blocks(GROUP_H_SIZE + dlen);
930 struct tipc_group *grp = tsk->group; 930 struct tipc_group *grp = tsk->group;
931 struct tipc_msg *hdr = &tsk->phdr;
931 struct tipc_member *first = NULL; 932 struct tipc_member *first = NULL;
932 struct tipc_member *mbr = NULL; 933 struct tipc_member *mbr = NULL;
933 struct net *net = sock_net(sk); 934 struct net *net = sock_net(sk);
934 u32 node, port, exclude; 935 u32 node, port, exclude;
935 u32 type, inst, domain;
936 struct list_head dsts; 936 struct list_head dsts;
937 u32 type, inst, scope;
937 int lookups = 0; 938 int lookups = 0;
938 int dstcnt, rc; 939 int dstcnt, rc;
939 bool cong; 940 bool cong;
940 941
941 INIT_LIST_HEAD(&dsts); 942 INIT_LIST_HEAD(&dsts);
942 943
943 type = dest->addr.name.name.type; 944 type = msg_nametype(hdr);
944 inst = dest->addr.name.name.instance; 945 inst = dest->addr.name.name.instance;
945 domain = addr_domain(net, dest->scope); 946 scope = msg_lookup_scope(hdr);
946 exclude = tipc_group_exclude(grp); 947 exclude = tipc_group_exclude(grp);
947 948
948 while (++lookups < 4) { 949 while (++lookups < 4) {
@@ -950,7 +951,7 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m,
950 951
951 /* Look for a non-congested destination member, if any */ 952 /* Look for a non-congested destination member, if any */
952 while (1) { 953 while (1) {
953 if (!tipc_nametbl_lookup(net, type, inst, domain, &dsts, 954 if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts,
954 &dstcnt, exclude, false)) 955 &dstcnt, exclude, false))
955 return -EHOSTUNREACH; 956 return -EHOSTUNREACH;
956 tipc_dest_pop(&dsts, &node, &port); 957 tipc_dest_pop(&dsts, &node, &port);
@@ -1079,22 +1080,23 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m,
1079{ 1080{
1080 struct sock *sk = sock->sk; 1081 struct sock *sk = sock->sk;
1081 DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); 1082 DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
1082 struct tipc_name_seq *seq = &dest->addr.nameseq;
1083 struct tipc_sock *tsk = tipc_sk(sk); 1083 struct tipc_sock *tsk = tipc_sk(sk);
1084 struct tipc_group *grp = tsk->group; 1084 struct tipc_group *grp = tsk->group;
1085 struct tipc_msg *hdr = &tsk->phdr;
1085 struct net *net = sock_net(sk); 1086 struct net *net = sock_net(sk);
1086 u32 domain, exclude, dstcnt; 1087 u32 type, inst, scope, exclude;
1087 struct list_head dsts; 1088 struct list_head dsts;
1089 u32 dstcnt;
1088 1090
1089 INIT_LIST_HEAD(&dsts); 1091 INIT_LIST_HEAD(&dsts);
1090 1092
1091 if (seq->lower != seq->upper) 1093 type = msg_nametype(hdr);
1092 return -ENOTSUPP; 1094 inst = dest->addr.name.name.instance;
1093 1095 scope = msg_lookup_scope(hdr);
1094 domain = addr_domain(net, dest->scope);
1095 exclude = tipc_group_exclude(grp); 1096 exclude = tipc_group_exclude(grp);
1096 if (!tipc_nametbl_lookup(net, seq->type, seq->lower, domain, 1097
1097 &dsts, &dstcnt, exclude, true)) 1098 if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts,
1099 &dstcnt, exclude, true))
1098 return -EHOSTUNREACH; 1100 return -EHOSTUNREACH;
1099 1101
1100 if (dstcnt == 1) { 1102 if (dstcnt == 1) {
@@ -1116,24 +1118,29 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m,
1116void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, 1118void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
1117 struct sk_buff_head *inputq) 1119 struct sk_buff_head *inputq)
1118{ 1120{
1119 u32 scope = TIPC_CLUSTER_SCOPE;
1120 u32 self = tipc_own_addr(net); 1121 u32 self = tipc_own_addr(net);
1122 u32 type, lower, upper, scope;
1121 struct sk_buff *skb, *_skb; 1123 struct sk_buff *skb, *_skb;
1122 u32 lower = 0, upper = ~0;
1123 struct sk_buff_head tmpq;
1124 u32 portid, oport, onode; 1124 u32 portid, oport, onode;
1125 struct sk_buff_head tmpq;
1125 struct list_head dports; 1126 struct list_head dports;
1126 struct tipc_msg *msg; 1127 struct tipc_msg *hdr;
1127 int user, mtyp, hsz; 1128 int user, mtyp, hlen;
1129 bool exact;
1128 1130
1129 __skb_queue_head_init(&tmpq); 1131 __skb_queue_head_init(&tmpq);
1130 INIT_LIST_HEAD(&dports); 1132 INIT_LIST_HEAD(&dports);
1131 1133
1132 skb = tipc_skb_peek(arrvq, &inputq->lock); 1134 skb = tipc_skb_peek(arrvq, &inputq->lock);
1133 for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { 1135 for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) {
1134 msg = buf_msg(skb); 1136 hdr = buf_msg(skb);
1135 user = msg_user(msg); 1137 user = msg_user(hdr);
1136 mtyp = msg_type(msg); 1138 mtyp = msg_type(hdr);
1139 hlen = skb_headroom(skb) + msg_hdr_sz(hdr);
1140 oport = msg_origport(hdr);
1141 onode = msg_orignode(hdr);
1142 type = msg_nametype(hdr);
1143
1137 if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { 1144 if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) {
1138 spin_lock_bh(&inputq->lock); 1145 spin_lock_bh(&inputq->lock);
1139 if (skb_peek(arrvq) == skb) { 1146 if (skb_peek(arrvq) == skb) {
@@ -1144,21 +1151,31 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
1144 spin_unlock_bh(&inputq->lock); 1151 spin_unlock_bh(&inputq->lock);
1145 continue; 1152 continue;
1146 } 1153 }
1147 hsz = skb_headroom(skb) + msg_hdr_sz(msg); 1154
1148 oport = msg_origport(msg); 1155 /* Group messages require exact scope match */
1149 onode = msg_orignode(msg); 1156 if (msg_in_group(hdr)) {
1150 if (onode == self) 1157 lower = 0;
1151 scope = TIPC_NODE_SCOPE; 1158 upper = ~0;
1152 1159 scope = msg_lookup_scope(hdr);
1153 /* Create destination port list and message clones: */ 1160 exact = true;
1154 if (!msg_in_group(msg)) { 1161 } else {
1155 lower = msg_namelower(msg); 1162 /* TIPC_NODE_SCOPE means "any scope" in this context */
1156 upper = msg_nameupper(msg); 1163 if (onode == self)
1164 scope = TIPC_NODE_SCOPE;
1165 else
1166 scope = TIPC_CLUSTER_SCOPE;
1167 exact = false;
1168 lower = msg_namelower(hdr);
1169 upper = msg_nameupper(hdr);
1157 } 1170 }
1158 tipc_nametbl_mc_translate(net, msg_nametype(msg), lower, upper, 1171
1159 scope, &dports); 1172 /* Create destination port list: */
1173 tipc_nametbl_mc_lookup(net, type, lower, upper,
1174 scope, exact, &dports);
1175
1176 /* Clone message per destination */
1160 while (tipc_dest_pop(&dports, NULL, &portid)) { 1177 while (tipc_dest_pop(&dports, NULL, &portid)) {
1161 _skb = __pskb_copy(skb, hsz, GFP_ATOMIC); 1178 _skb = __pskb_copy(skb, hlen, GFP_ATOMIC);
1162 if (_skb) { 1179 if (_skb) {
1163 msg_set_destport(buf_msg(_skb), portid); 1180 msg_set_destport(buf_msg(_skb), portid);
1164 __skb_queue_tail(&tmpq, _skb); 1181 __skb_queue_tail(&tmpq, _skb);
@@ -2731,7 +2748,6 @@ void tipc_sk_rht_destroy(struct net *net)
2731static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) 2748static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
2732{ 2749{
2733 struct net *net = sock_net(&tsk->sk); 2750 struct net *net = sock_net(&tsk->sk);
2734 u32 domain = addr_domain(net, mreq->scope);
2735 struct tipc_group *grp = tsk->group; 2751 struct tipc_group *grp = tsk->group;
2736 struct tipc_msg *hdr = &tsk->phdr; 2752 struct tipc_msg *hdr = &tsk->phdr;
2737 struct tipc_name_seq seq; 2753 struct tipc_name_seq seq;
@@ -2739,6 +2755,8 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
2739 2755
2740 if (mreq->type < TIPC_RESERVED_TYPES) 2756 if (mreq->type < TIPC_RESERVED_TYPES)
2741 return -EACCES; 2757 return -EACCES;
2758 if (mreq->scope > TIPC_NODE_SCOPE)
2759 return -EINVAL;
2742 if (grp) 2760 if (grp)
2743 return -EACCES; 2761 return -EACCES;
2744 grp = tipc_group_create(net, tsk->portid, mreq); 2762 grp = tipc_group_create(net, tsk->portid, mreq);
@@ -2751,7 +2769,7 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
2751 seq.type = mreq->type; 2769 seq.type = mreq->type;
2752 seq.lower = mreq->instance; 2770 seq.lower = mreq->instance;
2753 seq.upper = seq.lower; 2771 seq.upper = seq.lower;
2754 tipc_nametbl_build_group(net, grp, mreq->type, domain); 2772 tipc_nametbl_build_group(net, grp, mreq->type, mreq->scope);
2755 rc = tipc_sk_publish(tsk, mreq->scope, &seq); 2773 rc = tipc_sk_publish(tsk, mreq->scope, &seq);
2756 if (rc) { 2774 if (rc) {
2757 tipc_group_delete(net, grp); 2775 tipc_group_delete(net, grp);