diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/Makefile | 2 | ||||
-rw-r--r-- | net/tipc/addr.h | 1 | ||||
-rw-r--r-- | net/tipc/bearer.c | 8 | ||||
-rw-r--r-- | net/tipc/bearer.h | 2 | ||||
-rw-r--r-- | net/tipc/core.c | 1 | ||||
-rw-r--r-- | net/tipc/core.h | 15 | ||||
-rw-r--r-- | net/tipc/discover.c | 5 | ||||
-rw-r--r-- | net/tipc/link.c | 51 | ||||
-rw-r--r-- | net/tipc/monitor.c | 651 | ||||
-rw-r--r-- | net/tipc/monitor.h | 73 | ||||
-rw-r--r-- | net/tipc/node.c | 48 | ||||
-rw-r--r-- | net/tipc/server.c | 3 | ||||
-rw-r--r-- | net/tipc/udp_media.c | 24 |
13 files changed, 826 insertions, 58 deletions
diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 57e460be4692..31b9f9c52974 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile | |||
@@ -6,7 +6,7 @@ obj-$(CONFIG_TIPC) := tipc.o | |||
6 | 6 | ||
7 | tipc-y += addr.o bcast.o bearer.o \ | 7 | tipc-y += addr.o bcast.o bearer.o \ |
8 | core.o link.o discover.o msg.o \ | 8 | core.o link.o discover.o msg.o \ |
9 | name_distr.o subscr.o name_table.o net.o \ | 9 | name_distr.o subscr.o monitor.o name_table.o net.o \ |
10 | netlink.o netlink_compat.o node.o socket.o eth_media.o \ | 10 | netlink.o netlink_compat.o node.o socket.o eth_media.o \ |
11 | server.o socket.o | 11 | server.o socket.o |
12 | 12 | ||
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 93f7c983be33..64f4004a6fac 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
@@ -73,4 +73,5 @@ int tipc_addr_node_valid(u32 addr); | |||
73 | int tipc_in_scope(u32 domain, u32 addr); | 73 | int tipc_in_scope(u32 domain, u32 addr); |
74 | int tipc_addr_scope(u32 domain); | 74 | int tipc_addr_scope(u32 domain); |
75 | char *tipc_addr_string_fill(char *string, u32 addr); | 75 | char *tipc_addr_string_fill(char *string, u32 addr); |
76 | |||
76 | #endif | 77 | #endif |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index bf8f05c3eb82..8584cc48654c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/bearer.c: TIPC bearer code | 2 | * net/tipc/bearer.c: TIPC bearer code |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2006, 2013-2014, Ericsson AB | 4 | * Copyright (c) 1996-2006, 2013-2016, Ericsson AB |
5 | * Copyright (c) 2004-2006, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2006, 2010-2013, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -39,6 +39,7 @@ | |||
39 | #include "bearer.h" | 39 | #include "bearer.h" |
40 | #include "link.h" | 40 | #include "link.h" |
41 | #include "discover.h" | 41 | #include "discover.h" |
42 | #include "monitor.h" | ||
42 | #include "bcast.h" | 43 | #include "bcast.h" |
43 | #include "netlink.h" | 44 | #include "netlink.h" |
44 | 45 | ||
@@ -313,6 +314,10 @@ restart: | |||
313 | rcu_assign_pointer(tn->bearer_list[bearer_id], b); | 314 | rcu_assign_pointer(tn->bearer_list[bearer_id], b); |
314 | if (skb) | 315 | if (skb) |
315 | tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr); | 316 | tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr); |
317 | |||
318 | if (tipc_mon_create(net, bearer_id)) | ||
319 | return -ENOMEM; | ||
320 | |||
316 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 321 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
317 | name, | 322 | name, |
318 | tipc_addr_string_fill(addr_string, disc_domain), priority); | 323 | tipc_addr_string_fill(addr_string, disc_domain), priority); |
@@ -348,6 +353,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b) | |||
348 | tipc_disc_delete(b->link_req); | 353 | tipc_disc_delete(b->link_req); |
349 | RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL); | 354 | RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL); |
350 | kfree_rcu(b, rcu); | 355 | kfree_rcu(b, rcu); |
356 | tipc_mon_delete(net, bearer_id); | ||
351 | } | 357 | } |
352 | 358 | ||
353 | int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, | 359 | int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index f686e41b5abb..0d337c7b6fad 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/bearer.h: Include file for TIPC bearer code | 2 | * net/tipc/bearer.h: Include file for TIPC bearer code |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2006, 2013-2014, Ericsson AB | 4 | * Copyright (c) 1996-2006, 2013-2016, Ericsson AB |
5 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
diff --git a/net/tipc/core.c b/net/tipc/core.c index fe1b062c4f18..236b043a4156 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -57,6 +57,7 @@ static int __net_init tipc_init_net(struct net *net) | |||
57 | 57 | ||
58 | tn->net_id = 4711; | 58 | tn->net_id = 4711; |
59 | tn->own_addr = 0; | 59 | tn->own_addr = 0; |
60 | tn->mon_threshold = TIPC_DEF_MON_THRESHOLD; | ||
60 | get_random_bytes(&tn->random, sizeof(int)); | 61 | get_random_bytes(&tn->random, sizeof(int)); |
61 | INIT_LIST_HEAD(&tn->node_list); | 62 | INIT_LIST_HEAD(&tn->node_list); |
62 | spin_lock_init(&tn->node_list_lock); | 63 | spin_lock_init(&tn->node_list_lock); |
diff --git a/net/tipc/core.h b/net/tipc/core.h index eff58dc53aa1..a1845fb27d80 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -66,11 +66,13 @@ struct tipc_bc_base; | |||
66 | struct tipc_link; | 66 | struct tipc_link; |
67 | struct tipc_name_table; | 67 | struct tipc_name_table; |
68 | struct tipc_server; | 68 | struct tipc_server; |
69 | struct tipc_monitor; | ||
69 | 70 | ||
70 | #define TIPC_MOD_VER "2.0.0" | 71 | #define TIPC_MOD_VER "2.0.0" |
71 | 72 | ||
72 | #define NODE_HTABLE_SIZE 512 | 73 | #define NODE_HTABLE_SIZE 512 |
73 | #define MAX_BEARERS 3 | 74 | #define MAX_BEARERS 3 |
75 | #define TIPC_DEF_MON_THRESHOLD 32 | ||
74 | 76 | ||
75 | extern int tipc_net_id __read_mostly; | 77 | extern int tipc_net_id __read_mostly; |
76 | extern int sysctl_tipc_rmem[3] __read_mostly; | 78 | extern int sysctl_tipc_rmem[3] __read_mostly; |
@@ -88,6 +90,10 @@ struct tipc_net { | |||
88 | u32 num_nodes; | 90 | u32 num_nodes; |
89 | u32 num_links; | 91 | u32 num_links; |
90 | 92 | ||
93 | /* Neighbor monitoring list */ | ||
94 | struct tipc_monitor *monitors[MAX_BEARERS]; | ||
95 | int mon_threshold; | ||
96 | |||
91 | /* Bearer list */ | 97 | /* Bearer list */ |
92 | struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; | 98 | struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; |
93 | 99 | ||
@@ -126,6 +132,11 @@ static inline struct list_head *tipc_nodes(struct net *net) | |||
126 | return &tipc_net(net)->node_list; | 132 | return &tipc_net(net)->node_list; |
127 | } | 133 | } |
128 | 134 | ||
135 | static inline unsigned int tipc_hashfn(u32 addr) | ||
136 | { | ||
137 | return addr & (NODE_HTABLE_SIZE - 1); | ||
138 | } | ||
139 | |||
129 | static inline u16 mod(u16 x) | 140 | static inline u16 mod(u16 x) |
130 | { | 141 | { |
131 | return x & 0xffffu; | 142 | return x & 0xffffu; |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index ad9d477cc242..6b109a808d4c 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -135,9 +135,12 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, | |||
135 | u16 caps = msg_node_capabilities(hdr); | 135 | u16 caps = msg_node_capabilities(hdr); |
136 | bool respond = false; | 136 | bool respond = false; |
137 | bool dupl_addr = false; | 137 | bool dupl_addr = false; |
138 | int err; | ||
138 | 139 | ||
139 | bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr)); | 140 | err = bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr)); |
140 | kfree_skb(skb); | 141 | kfree_skb(skb); |
142 | if (err) | ||
143 | return; | ||
141 | 144 | ||
142 | /* Ensure message from node is valid and communication is permitted */ | 145 | /* Ensure message from node is valid and communication is permitted */ |
143 | if (net_id != tn->net_id) | 146 | if (net_id != tn->net_id) |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 67b6ab9f4c8d..c1df33f878b2 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "name_distr.h" | 42 | #include "name_distr.h" |
43 | #include "discover.h" | 43 | #include "discover.h" |
44 | #include "netlink.h" | 44 | #include "netlink.h" |
45 | #include "monitor.h" | ||
45 | 46 | ||
46 | #include <linux/pkt_sched.h> | 47 | #include <linux/pkt_sched.h> |
47 | 48 | ||
@@ -87,7 +88,6 @@ struct tipc_stats { | |||
87 | * @peer_bearer_id: bearer id used by link's peer endpoint | 88 | * @peer_bearer_id: bearer id used by link's peer endpoint |
88 | * @bearer_id: local bearer id used by link | 89 | * @bearer_id: local bearer id used by link |
89 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | 90 | * @tolerance: minimum link continuity loss needed to reset link [in ms] |
90 | * @keepalive_intv: link keepalive timer interval | ||
91 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | 91 | * @abort_limit: # of unacknowledged continuity probes needed to reset link |
92 | * @state: current state of link FSM | 92 | * @state: current state of link FSM |
93 | * @peer_caps: bitmap describing capabilities of peer node | 93 | * @peer_caps: bitmap describing capabilities of peer node |
@@ -96,6 +96,7 @@ struct tipc_stats { | |||
96 | * @pmsg: convenience pointer to "proto_msg" field | 96 | * @pmsg: convenience pointer to "proto_msg" field |
97 | * @priority: current link priority | 97 | * @priority: current link priority |
98 | * @net_plane: current link network plane ('A' through 'H') | 98 | * @net_plane: current link network plane ('A' through 'H') |
99 | * @mon_state: cookie with information needed by link monitor | ||
99 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) | 100 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) |
100 | * @exp_msg_count: # of tunnelled messages expected during link changeover | 101 | * @exp_msg_count: # of tunnelled messages expected during link changeover |
101 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset | 102 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset |
@@ -131,7 +132,6 @@ struct tipc_link { | |||
131 | u32 peer_bearer_id; | 132 | u32 peer_bearer_id; |
132 | u32 bearer_id; | 133 | u32 bearer_id; |
133 | u32 tolerance; | 134 | u32 tolerance; |
134 | unsigned long keepalive_intv; | ||
135 | u32 abort_limit; | 135 | u32 abort_limit; |
136 | u32 state; | 136 | u32 state; |
137 | u16 peer_caps; | 137 | u16 peer_caps; |
@@ -140,6 +140,7 @@ struct tipc_link { | |||
140 | char if_name[TIPC_MAX_IF_NAME]; | 140 | char if_name[TIPC_MAX_IF_NAME]; |
141 | u32 priority; | 141 | u32 priority; |
142 | char net_plane; | 142 | char net_plane; |
143 | struct tipc_mon_state mon_state; | ||
143 | u16 rst_cnt; | 144 | u16 rst_cnt; |
144 | 145 | ||
145 | /* Failover/synch */ | 146 | /* Failover/synch */ |
@@ -711,18 +712,25 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) | |||
711 | bool setup = false; | 712 | bool setup = false; |
712 | u16 bc_snt = l->bc_sndlink->snd_nxt - 1; | 713 | u16 bc_snt = l->bc_sndlink->snd_nxt - 1; |
713 | u16 bc_acked = l->bc_rcvlink->acked; | 714 | u16 bc_acked = l->bc_rcvlink->acked; |
714 | 715 | struct tipc_mon_state *mstate = &l->mon_state; | |
715 | link_profile_stats(l); | ||
716 | 716 | ||
717 | switch (l->state) { | 717 | switch (l->state) { |
718 | case LINK_ESTABLISHED: | 718 | case LINK_ESTABLISHED: |
719 | case LINK_SYNCHING: | 719 | case LINK_SYNCHING: |
720 | if (l->silent_intv_cnt > l->abort_limit) | ||
721 | return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | ||
722 | mtyp = STATE_MSG; | 720 | mtyp = STATE_MSG; |
721 | link_profile_stats(l); | ||
722 | tipc_mon_get_state(l->net, l->addr, mstate, l->bearer_id); | ||
723 | if (mstate->reset || (l->silent_intv_cnt > l->abort_limit)) | ||
724 | return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | ||
723 | state = bc_acked != bc_snt; | 725 | state = bc_acked != bc_snt; |
724 | probe = l->silent_intv_cnt; | 726 | state |= l->bc_rcvlink->rcv_unacked; |
725 | l->silent_intv_cnt++; | 727 | state |= l->rcv_unacked; |
728 | state |= !skb_queue_empty(&l->transmq); | ||
729 | state |= !skb_queue_empty(&l->deferdq); | ||
730 | probe = mstate->probing; | ||
731 | probe |= l->silent_intv_cnt; | ||
732 | if (probe || mstate->monitoring) | ||
733 | l->silent_intv_cnt++; | ||
726 | break; | 734 | break; |
727 | case LINK_RESET: | 735 | case LINK_RESET: |
728 | setup = l->rst_cnt++ <= 4; | 736 | setup = l->rst_cnt++ <= 4; |
@@ -833,6 +841,7 @@ void tipc_link_reset(struct tipc_link *l) | |||
833 | l->stats.recv_info = 0; | 841 | l->stats.recv_info = 0; |
834 | l->stale_count = 0; | 842 | l->stale_count = 0; |
835 | l->bc_peer_is_up = false; | 843 | l->bc_peer_is_up = false; |
844 | memset(&l->mon_state, 0, sizeof(l->mon_state)); | ||
836 | tipc_link_reset_stats(l); | 845 | tipc_link_reset_stats(l); |
837 | } | 846 | } |
838 | 847 | ||
@@ -1241,6 +1250,9 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
1241 | struct tipc_msg *hdr; | 1250 | struct tipc_msg *hdr; |
1242 | struct sk_buff_head *dfq = &l->deferdq; | 1251 | struct sk_buff_head *dfq = &l->deferdq; |
1243 | bool node_up = link_is_up(l->bc_rcvlink); | 1252 | bool node_up = link_is_up(l->bc_rcvlink); |
1253 | struct tipc_mon_state *mstate = &l->mon_state; | ||
1254 | int dlen = 0; | ||
1255 | void *data; | ||
1244 | 1256 | ||
1245 | /* Don't send protocol message during reset or link failover */ | 1257 | /* Don't send protocol message during reset or link failover */ |
1246 | if (tipc_link_is_blocked(l)) | 1258 | if (tipc_link_is_blocked(l)) |
@@ -1253,12 +1265,13 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
1253 | rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt; | 1265 | rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt; |
1254 | 1266 | ||
1255 | skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE, | 1267 | skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE, |
1256 | TIPC_MAX_IF_NAME, l->addr, | 1268 | tipc_max_domain_size, l->addr, |
1257 | tipc_own_addr(l->net), 0, 0, 0); | 1269 | tipc_own_addr(l->net), 0, 0, 0); |
1258 | if (!skb) | 1270 | if (!skb) |
1259 | return; | 1271 | return; |
1260 | 1272 | ||
1261 | hdr = buf_msg(skb); | 1273 | hdr = buf_msg(skb); |
1274 | data = msg_data(hdr); | ||
1262 | msg_set_session(hdr, l->session); | 1275 | msg_set_session(hdr, l->session); |
1263 | msg_set_bearer_id(hdr, l->bearer_id); | 1276 | msg_set_bearer_id(hdr, l->bearer_id); |
1264 | msg_set_net_plane(hdr, l->net_plane); | 1277 | msg_set_net_plane(hdr, l->net_plane); |
@@ -1274,14 +1287,18 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
1274 | 1287 | ||
1275 | if (mtyp == STATE_MSG) { | 1288 | if (mtyp == STATE_MSG) { |
1276 | msg_set_seq_gap(hdr, rcvgap); | 1289 | msg_set_seq_gap(hdr, rcvgap); |
1277 | msg_set_size(hdr, INT_H_SIZE); | ||
1278 | msg_set_probe(hdr, probe); | 1290 | msg_set_probe(hdr, probe); |
1291 | tipc_mon_prep(l->net, data, &dlen, mstate, l->bearer_id); | ||
1292 | msg_set_size(hdr, INT_H_SIZE + dlen); | ||
1293 | skb_trim(skb, INT_H_SIZE + dlen); | ||
1279 | l->stats.sent_states++; | 1294 | l->stats.sent_states++; |
1280 | l->rcv_unacked = 0; | 1295 | l->rcv_unacked = 0; |
1281 | } else { | 1296 | } else { |
1282 | /* RESET_MSG or ACTIVATE_MSG */ | 1297 | /* RESET_MSG or ACTIVATE_MSG */ |
1283 | msg_set_max_pkt(hdr, l->advertised_mtu); | 1298 | msg_set_max_pkt(hdr, l->advertised_mtu); |
1284 | strcpy(msg_data(hdr), l->if_name); | 1299 | strcpy(data, l->if_name); |
1300 | msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME); | ||
1301 | skb_trim(skb, INT_H_SIZE + TIPC_MAX_IF_NAME); | ||
1285 | } | 1302 | } |
1286 | if (probe) | 1303 | if (probe) |
1287 | l->stats.sent_probes++; | 1304 | l->stats.sent_probes++; |
@@ -1374,7 +1391,9 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1374 | u16 peers_tol = msg_link_tolerance(hdr); | 1391 | u16 peers_tol = msg_link_tolerance(hdr); |
1375 | u16 peers_prio = msg_linkprio(hdr); | 1392 | u16 peers_prio = msg_linkprio(hdr); |
1376 | u16 rcv_nxt = l->rcv_nxt; | 1393 | u16 rcv_nxt = l->rcv_nxt; |
1394 | u16 dlen = msg_data_sz(hdr); | ||
1377 | int mtyp = msg_type(hdr); | 1395 | int mtyp = msg_type(hdr); |
1396 | void *data; | ||
1378 | char *if_name; | 1397 | char *if_name; |
1379 | int rc = 0; | 1398 | int rc = 0; |
1380 | 1399 | ||
@@ -1384,6 +1403,10 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1384 | if (tipc_own_addr(l->net) > msg_prevnode(hdr)) | 1403 | if (tipc_own_addr(l->net) > msg_prevnode(hdr)) |
1385 | l->net_plane = msg_net_plane(hdr); | 1404 | l->net_plane = msg_net_plane(hdr); |
1386 | 1405 | ||
1406 | skb_linearize(skb); | ||
1407 | hdr = buf_msg(skb); | ||
1408 | data = msg_data(hdr); | ||
1409 | |||
1387 | switch (mtyp) { | 1410 | switch (mtyp) { |
1388 | case RESET_MSG: | 1411 | case RESET_MSG: |
1389 | 1412 | ||
@@ -1394,8 +1417,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1394 | /* fall thru' */ | 1417 | /* fall thru' */ |
1395 | 1418 | ||
1396 | case ACTIVATE_MSG: | 1419 | case ACTIVATE_MSG: |
1397 | skb_linearize(skb); | ||
1398 | hdr = buf_msg(skb); | ||
1399 | 1420 | ||
1400 | /* Complete own link name with peer's interface name */ | 1421 | /* Complete own link name with peer's interface name */ |
1401 | if_name = strrchr(l->name, ':') + 1; | 1422 | if_name = strrchr(l->name, ':') + 1; |
@@ -1403,7 +1424,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1403 | break; | 1424 | break; |
1404 | if (msg_data_sz(hdr) < TIPC_MAX_IF_NAME) | 1425 | if (msg_data_sz(hdr) < TIPC_MAX_IF_NAME) |
1405 | break; | 1426 | break; |
1406 | strncpy(if_name, msg_data(hdr), TIPC_MAX_IF_NAME); | 1427 | strncpy(if_name, data, TIPC_MAX_IF_NAME); |
1407 | 1428 | ||
1408 | /* Update own tolerance if peer indicates a non-zero value */ | 1429 | /* Update own tolerance if peer indicates a non-zero value */ |
1409 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) | 1430 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) |
@@ -1451,6 +1472,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1451 | rc = TIPC_LINK_UP_EVT; | 1472 | rc = TIPC_LINK_UP_EVT; |
1452 | break; | 1473 | break; |
1453 | } | 1474 | } |
1475 | tipc_mon_rcv(l->net, data, dlen, l->addr, | ||
1476 | &l->mon_state, l->bearer_id); | ||
1454 | 1477 | ||
1455 | /* Send NACK if peer has sent pkts we haven't received yet */ | 1478 | /* Send NACK if peer has sent pkts we haven't received yet */ |
1456 | if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l)) | 1479 | if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l)) |
diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c new file mode 100644 index 000000000000..0d489e81fcca --- /dev/null +++ b/net/tipc/monitor.c | |||
@@ -0,0 +1,651 @@ | |||
1 | /* | ||
2 | * net/tipc/monitor.c | ||
3 | * | ||
4 | * Copyright (c) 2016, Ericsson AB | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions are met: | ||
9 | * | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the names of the copyright holders nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived from | ||
17 | * this software without specific prior written permission. | ||
18 | * | ||
19 | * Alternatively, this software may be distributed under the terms of the | ||
20 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
21 | * Software Foundation. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
33 | * POSSIBILITY OF SUCH DAMAGE. | ||
34 | */ | ||
35 | |||
36 | #include "core.h" | ||
37 | #include "addr.h" | ||
38 | #include "monitor.h" | ||
39 | |||
40 | #define MAX_MON_DOMAIN 64 | ||
41 | #define MON_TIMEOUT 120000 | ||
42 | #define MAX_PEER_DOWN_EVENTS 4 | ||
43 | |||
44 | /* struct tipc_mon_domain: domain record to be transferred between peers | ||
45 | * @len: actual size of domain record | ||
46 | * @gen: current generation of sender's domain | ||
47 | * @ack_gen: most recent generation of self's domain acked by peer | ||
48 | * @member_cnt: number of domain member nodes described in this record | ||
49 | * @up_map: bit map indicating which of the members the sender considers up | ||
50 | * @members: identity of the domain members | ||
51 | */ | ||
52 | struct tipc_mon_domain { | ||
53 | u16 len; | ||
54 | u16 gen; | ||
55 | u16 ack_gen; | ||
56 | u16 member_cnt; | ||
57 | u64 up_map; | ||
58 | u32 members[MAX_MON_DOMAIN]; | ||
59 | }; | ||
60 | |||
61 | /* struct tipc_peer: state of a peer node and its domain | ||
62 | * @addr: tipc node identity of peer | ||
63 | * @head_map: shows which other nodes currently consider peer 'up' | ||
64 | * @domain: most recent domain record from peer | ||
65 | * @hash: position in hashed lookup list | ||
66 | * @list: position in linked list, in circular ascending order by 'addr' | ||
67 | * @applied: number of reported domain members applied on this monitor list | ||
68 | * @is_up: peer is up as seen from this node | ||
69 | * @is_head: peer is assigned domain head as seen from this node | ||
70 | * @is_local: peer is in local domain and should be continuously monitored | ||
71 | * @down_cnt: - numbers of other peers which have reported this on lost | ||
72 | */ | ||
73 | struct tipc_peer { | ||
74 | u32 addr; | ||
75 | struct tipc_mon_domain *domain; | ||
76 | struct hlist_node hash; | ||
77 | struct list_head list; | ||
78 | u8 applied; | ||
79 | u8 down_cnt; | ||
80 | bool is_up; | ||
81 | bool is_head; | ||
82 | bool is_local; | ||
83 | }; | ||
84 | |||
85 | struct tipc_monitor { | ||
86 | struct hlist_head peers[NODE_HTABLE_SIZE]; | ||
87 | int peer_cnt; | ||
88 | struct tipc_peer *self; | ||
89 | rwlock_t lock; | ||
90 | struct tipc_mon_domain cache; | ||
91 | u16 list_gen; | ||
92 | u16 dom_gen; | ||
93 | struct net *net; | ||
94 | struct timer_list timer; | ||
95 | unsigned long timer_intv; | ||
96 | }; | ||
97 | |||
98 | static struct tipc_monitor *tipc_monitor(struct net *net, int bearer_id) | ||
99 | { | ||
100 | return tipc_net(net)->monitors[bearer_id]; | ||
101 | } | ||
102 | |||
103 | const int tipc_max_domain_size = sizeof(struct tipc_mon_domain); | ||
104 | |||
105 | /* dom_rec_len(): actual length of domain record for transport | ||
106 | */ | ||
107 | static int dom_rec_len(struct tipc_mon_domain *dom, u16 mcnt) | ||
108 | { | ||
109 | return ((void *)&dom->members - (void *)dom) + (mcnt * sizeof(u32)); | ||
110 | } | ||
111 | |||
112 | /* dom_size() : calculate size of own domain based on number of peers | ||
113 | */ | ||
114 | static int dom_size(int peers) | ||
115 | { | ||
116 | int i = 0; | ||
117 | |||
118 | while ((i * i) < peers) | ||
119 | i++; | ||
120 | return i < MAX_MON_DOMAIN ? i : MAX_MON_DOMAIN; | ||
121 | } | ||
122 | |||
123 | static void map_set(u64 *up_map, int i, unsigned int v) | ||
124 | { | ||
125 | *up_map &= ~(1ULL << i); | ||
126 | *up_map |= ((u64)v << i); | ||
127 | } | ||
128 | |||
129 | static int map_get(u64 up_map, int i) | ||
130 | { | ||
131 | return (up_map & (1 << i)) >> i; | ||
132 | } | ||
133 | |||
134 | static struct tipc_peer *peer_prev(struct tipc_peer *peer) | ||
135 | { | ||
136 | return list_last_entry(&peer->list, struct tipc_peer, list); | ||
137 | } | ||
138 | |||
139 | static struct tipc_peer *peer_nxt(struct tipc_peer *peer) | ||
140 | { | ||
141 | return list_first_entry(&peer->list, struct tipc_peer, list); | ||
142 | } | ||
143 | |||
144 | static struct tipc_peer *peer_head(struct tipc_peer *peer) | ||
145 | { | ||
146 | while (!peer->is_head) | ||
147 | peer = peer_prev(peer); | ||
148 | return peer; | ||
149 | } | ||
150 | |||
151 | static struct tipc_peer *get_peer(struct tipc_monitor *mon, u32 addr) | ||
152 | { | ||
153 | struct tipc_peer *peer; | ||
154 | unsigned int thash = tipc_hashfn(addr); | ||
155 | |||
156 | hlist_for_each_entry(peer, &mon->peers[thash], hash) { | ||
157 | if (peer->addr == addr) | ||
158 | return peer; | ||
159 | } | ||
160 | return NULL; | ||
161 | } | ||
162 | |||
163 | static struct tipc_peer *get_self(struct net *net, int bearer_id) | ||
164 | { | ||
165 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
166 | |||
167 | return mon->self; | ||
168 | } | ||
169 | |||
170 | static inline bool tipc_mon_is_active(struct net *net, struct tipc_monitor *mon) | ||
171 | { | ||
172 | struct tipc_net *tn = tipc_net(net); | ||
173 | |||
174 | return mon->peer_cnt > tn->mon_threshold; | ||
175 | } | ||
176 | |||
177 | /* mon_identify_lost_members() : - identify amd mark potentially lost members | ||
178 | */ | ||
179 | static void mon_identify_lost_members(struct tipc_peer *peer, | ||
180 | struct tipc_mon_domain *dom_bef, | ||
181 | int applied_bef) | ||
182 | { | ||
183 | struct tipc_peer *member = peer; | ||
184 | struct tipc_mon_domain *dom_aft = peer->domain; | ||
185 | int applied_aft = peer->applied; | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < applied_bef; i++) { | ||
189 | member = peer_nxt(member); | ||
190 | |||
191 | /* Do nothing if self or peer already see member as down */ | ||
192 | if (!member->is_up || !map_get(dom_bef->up_map, i)) | ||
193 | continue; | ||
194 | |||
195 | /* Loss of local node must be detected by active probing */ | ||
196 | if (member->is_local) | ||
197 | continue; | ||
198 | |||
199 | /* Start probing if member was removed from applied domain */ | ||
200 | if (!applied_aft || (applied_aft < i)) { | ||
201 | member->down_cnt = 1; | ||
202 | continue; | ||
203 | } | ||
204 | |||
205 | /* Member loss is confirmed if it is still in applied domain */ | ||
206 | if (!map_get(dom_aft->up_map, i)) | ||
207 | member->down_cnt++; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | /* mon_apply_domain() : match a peer's domain record against monitor list | ||
212 | */ | ||
213 | static void mon_apply_domain(struct tipc_monitor *mon, | ||
214 | struct tipc_peer *peer) | ||
215 | { | ||
216 | struct tipc_mon_domain *dom = peer->domain; | ||
217 | struct tipc_peer *member; | ||
218 | u32 addr; | ||
219 | int i; | ||
220 | |||
221 | if (!dom || !peer->is_up) | ||
222 | return; | ||
223 | |||
224 | /* Scan across domain members and match against monitor list */ | ||
225 | peer->applied = 0; | ||
226 | member = peer_nxt(peer); | ||
227 | for (i = 0; i < dom->member_cnt; i++) { | ||
228 | addr = dom->members[i]; | ||
229 | if (addr != member->addr) | ||
230 | return; | ||
231 | peer->applied++; | ||
232 | member = peer_nxt(member); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /* mon_update_local_domain() : update after peer addition/removal/up/down | ||
237 | */ | ||
238 | static void mon_update_local_domain(struct tipc_monitor *mon) | ||
239 | { | ||
240 | struct tipc_peer *self = mon->self; | ||
241 | struct tipc_mon_domain *cache = &mon->cache; | ||
242 | struct tipc_mon_domain *dom = self->domain; | ||
243 | struct tipc_peer *peer = self; | ||
244 | u64 prev_up_map = dom->up_map; | ||
245 | u16 member_cnt, i; | ||
246 | bool diff; | ||
247 | |||
248 | /* Update local domain size based on current size of cluster */ | ||
249 | member_cnt = dom_size(mon->peer_cnt) - 1; | ||
250 | self->applied = member_cnt; | ||
251 | |||
252 | /* Update native and cached outgoing local domain records */ | ||
253 | dom->len = dom_rec_len(dom, member_cnt); | ||
254 | diff = dom->member_cnt != member_cnt; | ||
255 | dom->member_cnt = member_cnt; | ||
256 | for (i = 0; i < member_cnt; i++) { | ||
257 | peer = peer_nxt(peer); | ||
258 | diff |= dom->members[i] != peer->addr; | ||
259 | dom->members[i] = peer->addr; | ||
260 | map_set(&dom->up_map, i, peer->is_up); | ||
261 | cache->members[i] = htonl(peer->addr); | ||
262 | } | ||
263 | diff |= dom->up_map != prev_up_map; | ||
264 | if (!diff) | ||
265 | return; | ||
266 | dom->gen = ++mon->dom_gen; | ||
267 | cache->len = htons(dom->len); | ||
268 | cache->gen = htons(dom->gen); | ||
269 | cache->member_cnt = htons(member_cnt); | ||
270 | cache->up_map = cpu_to_be64(dom->up_map); | ||
271 | mon_apply_domain(mon, self); | ||
272 | } | ||
273 | |||
274 | /* mon_update_neighbors() : update preceding neighbors of added/removed peer | ||
275 | */ | ||
276 | static void mon_update_neighbors(struct tipc_monitor *mon, | ||
277 | struct tipc_peer *peer) | ||
278 | { | ||
279 | int dz, i; | ||
280 | |||
281 | dz = dom_size(mon->peer_cnt); | ||
282 | for (i = 0; i < dz; i++) { | ||
283 | mon_apply_domain(mon, peer); | ||
284 | peer = peer_prev(peer); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | /* mon_assign_roles() : reassign peer roles after a network change | ||
289 | * The monitor list is consistent at this stage; i.e., each peer is monitoring | ||
290 | * a set of domain members as matched between domain record and the monitor list | ||
291 | */ | ||
292 | static void mon_assign_roles(struct tipc_monitor *mon, struct tipc_peer *head) | ||
293 | { | ||
294 | struct tipc_peer *peer = peer_nxt(head); | ||
295 | struct tipc_peer *self = mon->self; | ||
296 | int i = 0; | ||
297 | |||
298 | for (; peer != self; peer = peer_nxt(peer)) { | ||
299 | peer->is_local = false; | ||
300 | |||
301 | /* Update domain member */ | ||
302 | if (i++ < head->applied) { | ||
303 | peer->is_head = false; | ||
304 | if (head == self) | ||
305 | peer->is_local = true; | ||
306 | continue; | ||
307 | } | ||
308 | /* Assign next domain head */ | ||
309 | if (!peer->is_up) | ||
310 | continue; | ||
311 | if (peer->is_head) | ||
312 | break; | ||
313 | head = peer; | ||
314 | head->is_head = true; | ||
315 | i = 0; | ||
316 | } | ||
317 | mon->list_gen++; | ||
318 | } | ||
319 | |||
320 | void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id) | ||
321 | { | ||
322 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
323 | struct tipc_peer *self = get_self(net, bearer_id); | ||
324 | struct tipc_peer *peer, *prev, *head; | ||
325 | |||
326 | write_lock_bh(&mon->lock); | ||
327 | peer = get_peer(mon, addr); | ||
328 | if (!peer) | ||
329 | goto exit; | ||
330 | prev = peer_prev(peer); | ||
331 | list_del(&peer->list); | ||
332 | hlist_del(&peer->hash); | ||
333 | kfree(peer->domain); | ||
334 | kfree(peer); | ||
335 | mon->peer_cnt--; | ||
336 | head = peer_head(prev); | ||
337 | if (head == self) | ||
338 | mon_update_local_domain(mon); | ||
339 | mon_update_neighbors(mon, prev); | ||
340 | |||
341 | /* Revert to full-mesh monitoring if we reach threshold */ | ||
342 | if (!tipc_mon_is_active(net, mon)) { | ||
343 | list_for_each_entry(peer, &self->list, list) { | ||
344 | kfree(peer->domain); | ||
345 | peer->domain = NULL; | ||
346 | peer->applied = 0; | ||
347 | } | ||
348 | } | ||
349 | mon_assign_roles(mon, head); | ||
350 | exit: | ||
351 | write_unlock_bh(&mon->lock); | ||
352 | } | ||
353 | |||
354 | static bool tipc_mon_add_peer(struct tipc_monitor *mon, u32 addr, | ||
355 | struct tipc_peer **peer) | ||
356 | { | ||
357 | struct tipc_peer *self = mon->self; | ||
358 | struct tipc_peer *cur, *prev, *p; | ||
359 | |||
360 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | ||
361 | *peer = p; | ||
362 | if (!p) | ||
363 | return false; | ||
364 | p->addr = addr; | ||
365 | |||
366 | /* Add new peer to lookup list */ | ||
367 | INIT_LIST_HEAD(&p->list); | ||
368 | hlist_add_head(&p->hash, &mon->peers[tipc_hashfn(addr)]); | ||
369 | |||
370 | /* Sort new peer into iterator list, in ascending circular order */ | ||
371 | prev = self; | ||
372 | list_for_each_entry(cur, &self->list, list) { | ||
373 | if ((addr > prev->addr) && (addr < cur->addr)) | ||
374 | break; | ||
375 | if (((addr < cur->addr) || (addr > prev->addr)) && | ||
376 | (prev->addr > cur->addr)) | ||
377 | break; | ||
378 | prev = cur; | ||
379 | } | ||
380 | list_add_tail(&p->list, &cur->list); | ||
381 | mon->peer_cnt++; | ||
382 | mon_update_neighbors(mon, p); | ||
383 | return true; | ||
384 | } | ||
385 | |||
386 | void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id) | ||
387 | { | ||
388 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
389 | struct tipc_peer *self = get_self(net, bearer_id); | ||
390 | struct tipc_peer *peer, *head; | ||
391 | |||
392 | write_lock_bh(&mon->lock); | ||
393 | peer = get_peer(mon, addr); | ||
394 | if (!peer && !tipc_mon_add_peer(mon, addr, &peer)) | ||
395 | goto exit; | ||
396 | peer->is_up = true; | ||
397 | head = peer_head(peer); | ||
398 | if (head == self) | ||
399 | mon_update_local_domain(mon); | ||
400 | mon_assign_roles(mon, head); | ||
401 | exit: | ||
402 | write_unlock_bh(&mon->lock); | ||
403 | } | ||
404 | |||
405 | void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id) | ||
406 | { | ||
407 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
408 | struct tipc_peer *self = get_self(net, bearer_id); | ||
409 | struct tipc_peer *peer, *head; | ||
410 | struct tipc_mon_domain *dom; | ||
411 | int applied; | ||
412 | |||
413 | write_lock_bh(&mon->lock); | ||
414 | peer = get_peer(mon, addr); | ||
415 | if (!peer) { | ||
416 | pr_warn("Mon: unknown link %x/%u DOWN\n", addr, bearer_id); | ||
417 | goto exit; | ||
418 | } | ||
419 | applied = peer->applied; | ||
420 | peer->applied = 0; | ||
421 | dom = peer->domain; | ||
422 | peer->domain = NULL; | ||
423 | if (peer->is_head) | ||
424 | mon_identify_lost_members(peer, dom, applied); | ||
425 | kfree(dom); | ||
426 | peer->is_up = false; | ||
427 | peer->is_head = false; | ||
428 | peer->is_local = false; | ||
429 | peer->down_cnt = 0; | ||
430 | head = peer_head(peer); | ||
431 | if (head == self) | ||
432 | mon_update_local_domain(mon); | ||
433 | mon_assign_roles(mon, head); | ||
434 | exit: | ||
435 | write_unlock_bh(&mon->lock); | ||
436 | } | ||
437 | |||
438 | /* tipc_mon_rcv - process monitor domain event message | ||
439 | */ | ||
440 | void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr, | ||
441 | struct tipc_mon_state *state, int bearer_id) | ||
442 | { | ||
443 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
444 | struct tipc_mon_domain *arrv_dom = data; | ||
445 | struct tipc_mon_domain dom_bef; | ||
446 | struct tipc_mon_domain *dom; | ||
447 | struct tipc_peer *peer; | ||
448 | u16 new_member_cnt = ntohs(arrv_dom->member_cnt); | ||
449 | int new_dlen = dom_rec_len(arrv_dom, new_member_cnt); | ||
450 | u16 new_gen = ntohs(arrv_dom->gen); | ||
451 | u16 acked_gen = ntohs(arrv_dom->ack_gen); | ||
452 | bool probing = state->probing; | ||
453 | int i, applied_bef; | ||
454 | |||
455 | state->probing = false; | ||
456 | if (!dlen) | ||
457 | return; | ||
458 | |||
459 | /* Sanity check received domain record */ | ||
460 | if ((dlen < new_dlen) || ntohs(arrv_dom->len) != new_dlen) { | ||
461 | pr_warn_ratelimited("Received illegal domain record\n"); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | /* Synch generation numbers with peer if link just came up */ | ||
466 | if (!state->synched) { | ||
467 | state->peer_gen = new_gen - 1; | ||
468 | state->acked_gen = acked_gen; | ||
469 | state->synched = true; | ||
470 | } | ||
471 | |||
472 | if (more(acked_gen, state->acked_gen)) | ||
473 | state->acked_gen = acked_gen; | ||
474 | |||
475 | /* Drop duplicate unless we are waiting for a probe response */ | ||
476 | if (!more(new_gen, state->peer_gen) && !probing) | ||
477 | return; | ||
478 | |||
479 | write_lock_bh(&mon->lock); | ||
480 | peer = get_peer(mon, addr); | ||
481 | if (!peer || !peer->is_up) | ||
482 | goto exit; | ||
483 | |||
484 | /* Peer is confirmed, stop any ongoing probing */ | ||
485 | peer->down_cnt = 0; | ||
486 | |||
487 | /* Task is done for duplicate record */ | ||
488 | if (!more(new_gen, state->peer_gen)) | ||
489 | goto exit; | ||
490 | |||
491 | state->peer_gen = new_gen; | ||
492 | |||
493 | /* Cache current domain record for later use */ | ||
494 | dom_bef.member_cnt = 0; | ||
495 | dom = peer->domain; | ||
496 | if (dom) | ||
497 | memcpy(&dom_bef, dom, dom->len); | ||
498 | |||
499 | /* Transform and store received domain record */ | ||
500 | if (!dom || (dom->len < new_dlen)) { | ||
501 | kfree(dom); | ||
502 | dom = kmalloc(new_dlen, GFP_ATOMIC); | ||
503 | peer->domain = dom; | ||
504 | if (!dom) | ||
505 | goto exit; | ||
506 | } | ||
507 | dom->len = new_dlen; | ||
508 | dom->gen = new_gen; | ||
509 | dom->member_cnt = new_member_cnt; | ||
510 | dom->up_map = be64_to_cpu(arrv_dom->up_map); | ||
511 | for (i = 0; i < new_member_cnt; i++) | ||
512 | dom->members[i] = ntohl(arrv_dom->members[i]); | ||
513 | |||
514 | /* Update peers affected by this domain record */ | ||
515 | applied_bef = peer->applied; | ||
516 | mon_apply_domain(mon, peer); | ||
517 | mon_identify_lost_members(peer, &dom_bef, applied_bef); | ||
518 | mon_assign_roles(mon, peer_head(peer)); | ||
519 | exit: | ||
520 | write_unlock_bh(&mon->lock); | ||
521 | } | ||
522 | |||
523 | void tipc_mon_prep(struct net *net, void *data, int *dlen, | ||
524 | struct tipc_mon_state *state, int bearer_id) | ||
525 | { | ||
526 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
527 | struct tipc_mon_domain *dom = data; | ||
528 | u16 gen = mon->dom_gen; | ||
529 | u16 len; | ||
530 | |||
531 | if (!tipc_mon_is_active(net, mon)) | ||
532 | return; | ||
533 | |||
534 | /* Send only a dummy record with ack if peer has acked our last sent */ | ||
535 | if (likely(state->acked_gen == gen)) { | ||
536 | len = dom_rec_len(dom, 0); | ||
537 | *dlen = len; | ||
538 | dom->len = htons(len); | ||
539 | dom->gen = htons(gen); | ||
540 | dom->ack_gen = htons(state->peer_gen); | ||
541 | dom->member_cnt = 0; | ||
542 | return; | ||
543 | } | ||
544 | /* Send the full record */ | ||
545 | read_lock_bh(&mon->lock); | ||
546 | len = ntohs(mon->cache.len); | ||
547 | *dlen = len; | ||
548 | memcpy(data, &mon->cache, len); | ||
549 | read_unlock_bh(&mon->lock); | ||
550 | dom->ack_gen = htons(state->peer_gen); | ||
551 | } | ||
552 | |||
553 | void tipc_mon_get_state(struct net *net, u32 addr, | ||
554 | struct tipc_mon_state *state, | ||
555 | int bearer_id) | ||
556 | { | ||
557 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
558 | struct tipc_peer *peer; | ||
559 | |||
560 | /* Used cached state if table has not changed */ | ||
561 | if (!state->probing && | ||
562 | (state->list_gen == mon->list_gen) && | ||
563 | (state->acked_gen == mon->dom_gen)) | ||
564 | return; | ||
565 | |||
566 | read_lock_bh(&mon->lock); | ||
567 | peer = get_peer(mon, addr); | ||
568 | if (peer) { | ||
569 | state->probing = state->acked_gen != mon->dom_gen; | ||
570 | state->probing |= peer->down_cnt; | ||
571 | state->reset |= peer->down_cnt >= MAX_PEER_DOWN_EVENTS; | ||
572 | state->monitoring = peer->is_local; | ||
573 | state->monitoring |= peer->is_head; | ||
574 | state->list_gen = mon->list_gen; | ||
575 | } | ||
576 | read_unlock_bh(&mon->lock); | ||
577 | } | ||
578 | |||
579 | static void mon_timeout(unsigned long m) | ||
580 | { | ||
581 | struct tipc_monitor *mon = (void *)m; | ||
582 | struct tipc_peer *self; | ||
583 | int best_member_cnt = dom_size(mon->peer_cnt) - 1; | ||
584 | |||
585 | write_lock_bh(&mon->lock); | ||
586 | self = mon->self; | ||
587 | if (self && (best_member_cnt != self->applied)) { | ||
588 | mon_update_local_domain(mon); | ||
589 | mon_assign_roles(mon, self); | ||
590 | } | ||
591 | write_unlock_bh(&mon->lock); | ||
592 | mod_timer(&mon->timer, jiffies + mon->timer_intv); | ||
593 | } | ||
594 | |||
595 | int tipc_mon_create(struct net *net, int bearer_id) | ||
596 | { | ||
597 | struct tipc_net *tn = tipc_net(net); | ||
598 | struct tipc_monitor *mon; | ||
599 | struct tipc_peer *self; | ||
600 | struct tipc_mon_domain *dom; | ||
601 | |||
602 | if (tn->monitors[bearer_id]) | ||
603 | return 0; | ||
604 | |||
605 | mon = kzalloc(sizeof(*mon), GFP_ATOMIC); | ||
606 | self = kzalloc(sizeof(*self), GFP_ATOMIC); | ||
607 | dom = kzalloc(sizeof(*dom), GFP_ATOMIC); | ||
608 | if (!mon || !self || !dom) { | ||
609 | kfree(mon); | ||
610 | kfree(self); | ||
611 | kfree(dom); | ||
612 | return -ENOMEM; | ||
613 | } | ||
614 | tn->monitors[bearer_id] = mon; | ||
615 | rwlock_init(&mon->lock); | ||
616 | mon->net = net; | ||
617 | mon->peer_cnt = 1; | ||
618 | mon->self = self; | ||
619 | self->domain = dom; | ||
620 | self->addr = tipc_own_addr(net); | ||
621 | self->is_up = true; | ||
622 | self->is_head = true; | ||
623 | INIT_LIST_HEAD(&self->list); | ||
624 | setup_timer(&mon->timer, mon_timeout, (unsigned long)mon); | ||
625 | mon->timer_intv = msecs_to_jiffies(MON_TIMEOUT + (tn->random & 0xffff)); | ||
626 | mod_timer(&mon->timer, jiffies + mon->timer_intv); | ||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | void tipc_mon_delete(struct net *net, int bearer_id) | ||
631 | { | ||
632 | struct tipc_net *tn = tipc_net(net); | ||
633 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
634 | struct tipc_peer *self = get_self(net, bearer_id); | ||
635 | struct tipc_peer *peer, *tmp; | ||
636 | |||
637 | write_lock_bh(&mon->lock); | ||
638 | tn->monitors[bearer_id] = NULL; | ||
639 | list_for_each_entry_safe(peer, tmp, &self->list, list) { | ||
640 | list_del(&peer->list); | ||
641 | hlist_del(&peer->hash); | ||
642 | kfree(peer->domain); | ||
643 | kfree(peer); | ||
644 | } | ||
645 | mon->self = NULL; | ||
646 | write_unlock_bh(&mon->lock); | ||
647 | del_timer_sync(&mon->timer); | ||
648 | kfree(self->domain); | ||
649 | kfree(self); | ||
650 | kfree(mon); | ||
651 | } | ||
diff --git a/net/tipc/monitor.h b/net/tipc/monitor.h new file mode 100644 index 000000000000..598459cbed5d --- /dev/null +++ b/net/tipc/monitor.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * net/tipc/monitor.h | ||
3 | * | ||
4 | * Copyright (c) 2015, Ericsson AB | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions are met: | ||
9 | * | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the names of the copyright holders nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived from | ||
17 | * this software without specific prior written permission. | ||
18 | * | ||
19 | * Alternatively, this software may be distributed under the terms of the | ||
20 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
21 | * Software Foundation. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
33 | * POSSIBILITY OF SUCH DAMAGE. | ||
34 | */ | ||
35 | |||
36 | #ifndef _TIPC_MONITOR_H | ||
37 | #define _TIPC_MONITOR_H | ||
38 | |||
39 | /* struct tipc_mon_state: link instance's cache of monitor list and domain state | ||
40 | * @list_gen: current generation of this node's monitor list | ||
41 | * @gen: current generation of this node's local domain | ||
42 | * @peer_gen: most recent domain generation received from peer | ||
43 | * @acked_gen: most recent generation of self's domain acked by peer | ||
44 | * @monitoring: this peer endpoint should continuously monitored | ||
45 | * @probing: peer endpoint should be temporarily probed for potential loss | ||
46 | * @synched: domain record's generation has been synched with peer after reset | ||
47 | */ | ||
48 | struct tipc_mon_state { | ||
49 | u16 list_gen; | ||
50 | u16 peer_gen; | ||
51 | u16 acked_gen; | ||
52 | bool monitoring :1; | ||
53 | bool probing :1; | ||
54 | bool reset :1; | ||
55 | bool synched :1; | ||
56 | }; | ||
57 | |||
58 | int tipc_mon_create(struct net *net, int bearer_id); | ||
59 | void tipc_mon_delete(struct net *net, int bearer_id); | ||
60 | |||
61 | void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id); | ||
62 | void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id); | ||
63 | void tipc_mon_prep(struct net *net, void *data, int *dlen, | ||
64 | struct tipc_mon_state *state, int bearer_id); | ||
65 | void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr, | ||
66 | struct tipc_mon_state *state, int bearer_id); | ||
67 | void tipc_mon_get_state(struct net *net, u32 addr, | ||
68 | struct tipc_mon_state *state, | ||
69 | int bearer_id); | ||
70 | void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id); | ||
71 | |||
72 | extern const int tipc_max_domain_size; | ||
73 | #endif | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c index e01e2c71b5a1..a3fc0a3f4077 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "name_distr.h" | 40 | #include "name_distr.h" |
41 | #include "socket.h" | 41 | #include "socket.h" |
42 | #include "bcast.h" | 42 | #include "bcast.h" |
43 | #include "monitor.h" | ||
43 | #include "discover.h" | 44 | #include "discover.h" |
44 | #include "netlink.h" | 45 | #include "netlink.h" |
45 | 46 | ||
@@ -205,17 +206,6 @@ u16 tipc_node_get_capabilities(struct net *net, u32 addr) | |||
205 | return caps; | 206 | return caps; |
206 | } | 207 | } |
207 | 208 | ||
208 | /* | ||
209 | * A trivial power-of-two bitmask technique is used for speed, since this | ||
210 | * operation is done for every incoming TIPC packet. The number of hash table | ||
211 | * entries has been chosen so that no hash chain exceeds 8 nodes and will | ||
212 | * usually be much smaller (typically only a single node). | ||
213 | */ | ||
214 | static unsigned int tipc_hashfn(u32 addr) | ||
215 | { | ||
216 | return addr & (NODE_HTABLE_SIZE - 1); | ||
217 | } | ||
218 | |||
219 | static void tipc_node_kref_release(struct kref *kref) | 209 | static void tipc_node_kref_release(struct kref *kref) |
220 | { | 210 | { |
221 | struct tipc_node *n = container_of(kref, struct tipc_node, kref); | 211 | struct tipc_node *n = container_of(kref, struct tipc_node, kref); |
@@ -279,6 +269,7 @@ static void tipc_node_write_unlock(struct tipc_node *n) | |||
279 | u32 addr = 0; | 269 | u32 addr = 0; |
280 | u32 flags = n->action_flags; | 270 | u32 flags = n->action_flags; |
281 | u32 link_id = 0; | 271 | u32 link_id = 0; |
272 | u32 bearer_id; | ||
282 | struct list_head *publ_list; | 273 | struct list_head *publ_list; |
283 | 274 | ||
284 | if (likely(!flags)) { | 275 | if (likely(!flags)) { |
@@ -288,6 +279,7 @@ static void tipc_node_write_unlock(struct tipc_node *n) | |||
288 | 279 | ||
289 | addr = n->addr; | 280 | addr = n->addr; |
290 | link_id = n->link_id; | 281 | link_id = n->link_id; |
282 | bearer_id = link_id & 0xffff; | ||
291 | publ_list = &n->publ_list; | 283 | publ_list = &n->publ_list; |
292 | 284 | ||
293 | n->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | | 285 | n->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | |
@@ -301,13 +293,16 @@ static void tipc_node_write_unlock(struct tipc_node *n) | |||
301 | if (flags & TIPC_NOTIFY_NODE_UP) | 293 | if (flags & TIPC_NOTIFY_NODE_UP) |
302 | tipc_named_node_up(net, addr); | 294 | tipc_named_node_up(net, addr); |
303 | 295 | ||
304 | if (flags & TIPC_NOTIFY_LINK_UP) | 296 | if (flags & TIPC_NOTIFY_LINK_UP) { |
297 | tipc_mon_peer_up(net, addr, bearer_id); | ||
305 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | 298 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, |
306 | TIPC_NODE_SCOPE, link_id, addr); | 299 | TIPC_NODE_SCOPE, link_id, addr); |
307 | 300 | } | |
308 | if (flags & TIPC_NOTIFY_LINK_DOWN) | 301 | if (flags & TIPC_NOTIFY_LINK_DOWN) { |
302 | tipc_mon_peer_down(net, addr, bearer_id); | ||
309 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | 303 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, |
310 | link_id, addr); | 304 | link_id, addr); |
305 | } | ||
311 | } | 306 | } |
312 | 307 | ||
313 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | 308 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) |
@@ -378,14 +373,13 @@ static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l) | |||
378 | { | 373 | { |
379 | unsigned long tol = tipc_link_tolerance(l); | 374 | unsigned long tol = tipc_link_tolerance(l); |
380 | unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4; | 375 | unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4; |
381 | unsigned long keepalive_intv = msecs_to_jiffies(intv); | ||
382 | 376 | ||
383 | /* Link with lowest tolerance determines timer interval */ | 377 | /* Link with lowest tolerance determines timer interval */ |
384 | if (keepalive_intv < n->keepalive_intv) | 378 | if (intv < n->keepalive_intv) |
385 | n->keepalive_intv = keepalive_intv; | 379 | n->keepalive_intv = intv; |
386 | 380 | ||
387 | /* Ensure link's abort limit corresponds to current interval */ | 381 | /* Ensure link's abort limit corresponds to current tolerance */ |
388 | tipc_link_set_abort_limit(l, tol / jiffies_to_msecs(n->keepalive_intv)); | 382 | tipc_link_set_abort_limit(l, tol / n->keepalive_intv); |
389 | } | 383 | } |
390 | 384 | ||
391 | static void tipc_node_delete(struct tipc_node *node) | 385 | static void tipc_node_delete(struct tipc_node *node) |
@@ -526,7 +520,7 @@ static void tipc_node_timeout(unsigned long data) | |||
526 | if (rc & TIPC_LINK_DOWN_EVT) | 520 | if (rc & TIPC_LINK_DOWN_EVT) |
527 | tipc_node_link_down(n, bearer_id, false); | 521 | tipc_node_link_down(n, bearer_id, false); |
528 | } | 522 | } |
529 | mod_timer(&n->timer, jiffies + n->keepalive_intv); | 523 | mod_timer(&n->timer, jiffies + msecs_to_jiffies(n->keepalive_intv)); |
530 | } | 524 | } |
531 | 525 | ||
532 | /** | 526 | /** |
@@ -692,6 +686,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
692 | struct tipc_link *l = le->link; | 686 | struct tipc_link *l = le->link; |
693 | struct tipc_media_addr *maddr; | 687 | struct tipc_media_addr *maddr; |
694 | struct sk_buff_head xmitq; | 688 | struct sk_buff_head xmitq; |
689 | int old_bearer_id = bearer_id; | ||
695 | 690 | ||
696 | if (!l) | 691 | if (!l) |
697 | return; | 692 | return; |
@@ -711,6 +706,8 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
711 | tipc_link_fsm_evt(l, LINK_RESET_EVT); | 706 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
712 | } | 707 | } |
713 | tipc_node_write_unlock(n); | 708 | tipc_node_write_unlock(n); |
709 | if (delete) | ||
710 | tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); | ||
714 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); | 711 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); |
715 | tipc_sk_rcv(n->net, &le->inputq); | 712 | tipc_sk_rcv(n->net, &le->inputq); |
716 | } | 713 | } |
@@ -735,6 +732,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
735 | bool accept_addr = false; | 732 | bool accept_addr = false; |
736 | bool reset = true; | 733 | bool reset = true; |
737 | char *if_name; | 734 | char *if_name; |
735 | unsigned long intv; | ||
738 | 736 | ||
739 | *dupl_addr = false; | 737 | *dupl_addr = false; |
740 | *respond = false; | 738 | *respond = false; |
@@ -840,9 +838,11 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
840 | le->link = l; | 838 | le->link = l; |
841 | n->link_cnt++; | 839 | n->link_cnt++; |
842 | tipc_node_calculate_timer(n, l); | 840 | tipc_node_calculate_timer(n, l); |
843 | if (n->link_cnt == 1) | 841 | if (n->link_cnt == 1) { |
844 | if (!mod_timer(&n->timer, jiffies + n->keepalive_intv)) | 842 | intv = jiffies + msecs_to_jiffies(n->keepalive_intv); |
843 | if (!mod_timer(&n->timer, intv)) | ||
845 | tipc_node_get(n); | 844 | tipc_node_get(n); |
845 | } | ||
846 | } | 846 | } |
847 | memcpy(&le->maddr, maddr, sizeof(*maddr)); | 847 | memcpy(&le->maddr, maddr, sizeof(*maddr)); |
848 | exit: | 848 | exit: |
@@ -950,7 +950,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt) | |||
950 | state = SELF_UP_PEER_UP; | 950 | state = SELF_UP_PEER_UP; |
951 | break; | 951 | break; |
952 | case SELF_LOST_CONTACT_EVT: | 952 | case SELF_LOST_CONTACT_EVT: |
953 | state = SELF_DOWN_PEER_LEAVING; | 953 | state = SELF_DOWN_PEER_DOWN; |
954 | break; | 954 | break; |
955 | case SELF_ESTABL_CONTACT_EVT: | 955 | case SELF_ESTABL_CONTACT_EVT: |
956 | case PEER_LOST_CONTACT_EVT: | 956 | case PEER_LOST_CONTACT_EVT: |
@@ -969,7 +969,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt) | |||
969 | state = SELF_UP_PEER_UP; | 969 | state = SELF_UP_PEER_UP; |
970 | break; | 970 | break; |
971 | case PEER_LOST_CONTACT_EVT: | 971 | case PEER_LOST_CONTACT_EVT: |
972 | state = SELF_LEAVING_PEER_DOWN; | 972 | state = SELF_DOWN_PEER_DOWN; |
973 | break; | 973 | break; |
974 | case SELF_LOST_CONTACT_EVT: | 974 | case SELF_LOST_CONTACT_EVT: |
975 | case PEER_ESTABL_CONTACT_EVT: | 975 | case PEER_ESTABL_CONTACT_EVT: |
diff --git a/net/tipc/server.c b/net/tipc/server.c index 272d20a795d5..215849ce453d 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
@@ -418,13 +418,12 @@ static struct outqueue_entry *tipc_alloc_entry(void *data, int len) | |||
418 | if (!entry) | 418 | if (!entry) |
419 | return NULL; | 419 | return NULL; |
420 | 420 | ||
421 | buf = kmalloc(len, GFP_ATOMIC); | 421 | buf = kmemdup(data, len, GFP_ATOMIC); |
422 | if (!buf) { | 422 | if (!buf) { |
423 | kfree(entry); | 423 | kfree(entry); |
424 | return NULL; | 424 | return NULL; |
425 | } | 425 | } |
426 | 426 | ||
427 | memcpy(buf, data, len); | ||
428 | entry->iov.iov_base = buf; | 427 | entry->iov.iov_base = buf; |
429 | entry->iov.iov_len = len; | 428 | entry->iov.iov_len = len; |
430 | 429 | ||
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index c9cf2be3674a..b016c011970b 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -63,7 +63,7 @@ | |||
63 | */ | 63 | */ |
64 | struct udp_media_addr { | 64 | struct udp_media_addr { |
65 | __be16 proto; | 65 | __be16 proto; |
66 | __be16 udp_port; | 66 | __be16 port; |
67 | union { | 67 | union { |
68 | struct in_addr ipv4; | 68 | struct in_addr ipv4; |
69 | struct in6_addr ipv6; | 69 | struct in6_addr ipv6; |
@@ -108,9 +108,9 @@ static int tipc_udp_addr2str(struct tipc_media_addr *a, char *buf, int size) | |||
108 | struct udp_media_addr *ua = (struct udp_media_addr *)&a->value; | 108 | struct udp_media_addr *ua = (struct udp_media_addr *)&a->value; |
109 | 109 | ||
110 | if (ntohs(ua->proto) == ETH_P_IP) | 110 | if (ntohs(ua->proto) == ETH_P_IP) |
111 | snprintf(buf, size, "%pI4:%u", &ua->ipv4, ntohs(ua->udp_port)); | 111 | snprintf(buf, size, "%pI4:%u", &ua->ipv4, ntohs(ua->port)); |
112 | else if (ntohs(ua->proto) == ETH_P_IPV6) | 112 | else if (ntohs(ua->proto) == ETH_P_IPV6) |
113 | snprintf(buf, size, "%pI6:%u", &ua->ipv6, ntohs(ua->udp_port)); | 113 | snprintf(buf, size, "%pI6:%u", &ua->ipv6, ntohs(ua->port)); |
114 | else | 114 | else |
115 | pr_err("Invalid UDP media address\n"); | 115 | pr_err("Invalid UDP media address\n"); |
116 | return 0; | 116 | return 0; |
@@ -178,8 +178,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
178 | skb->dev = rt->dst.dev; | 178 | skb->dev = rt->dst.dev; |
179 | ttl = ip4_dst_hoplimit(&rt->dst); | 179 | ttl = ip4_dst_hoplimit(&rt->dst); |
180 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, | 180 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, |
181 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, | 181 | dst->ipv4.s_addr, 0, ttl, 0, src->port, |
182 | dst->udp_port, false, true); | 182 | dst->port, false, true); |
183 | #if IS_ENABLED(CONFIG_IPV6) | 183 | #if IS_ENABLED(CONFIG_IPV6) |
184 | } else { | 184 | } else { |
185 | struct dst_entry *ndst; | 185 | struct dst_entry *ndst; |
@@ -196,8 +196,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
196 | ttl = ip6_dst_hoplimit(ndst); | 196 | ttl = ip6_dst_hoplimit(ndst); |
197 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, | 197 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, |
198 | ndst->dev, &src->ipv6, | 198 | ndst->dev, &src->ipv6, |
199 | &dst->ipv6, 0, ttl, 0, src->udp_port, | 199 | &dst->ipv6, 0, ttl, 0, src->port, |
200 | dst->udp_port, false); | 200 | dst->port, false); |
201 | #endif | 201 | #endif |
202 | } | 202 | } |
203 | return err; | 203 | return err; |
@@ -292,12 +292,12 @@ err: | |||
292 | 292 | ||
293 | ip4 = (struct sockaddr_in *)&sa_local; | 293 | ip4 = (struct sockaddr_in *)&sa_local; |
294 | local->proto = htons(ETH_P_IP); | 294 | local->proto = htons(ETH_P_IP); |
295 | local->udp_port = ip4->sin_port; | 295 | local->port = ip4->sin_port; |
296 | local->ipv4.s_addr = ip4->sin_addr.s_addr; | 296 | local->ipv4.s_addr = ip4->sin_addr.s_addr; |
297 | 297 | ||
298 | ip4 = (struct sockaddr_in *)&sa_remote; | 298 | ip4 = (struct sockaddr_in *)&sa_remote; |
299 | remote->proto = htons(ETH_P_IP); | 299 | remote->proto = htons(ETH_P_IP); |
300 | remote->udp_port = ip4->sin_port; | 300 | remote->port = ip4->sin_port; |
301 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; | 301 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; |
302 | return 0; | 302 | return 0; |
303 | 303 | ||
@@ -312,13 +312,13 @@ err: | |||
312 | return -EINVAL; | 312 | return -EINVAL; |
313 | 313 | ||
314 | local->proto = htons(ETH_P_IPV6); | 314 | local->proto = htons(ETH_P_IPV6); |
315 | local->udp_port = ip6->sin6_port; | 315 | local->port = ip6->sin6_port; |
316 | memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); | 316 | memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
317 | ub->ifindex = ip6->sin6_scope_id; | 317 | ub->ifindex = ip6->sin6_scope_id; |
318 | 318 | ||
319 | ip6 = (struct sockaddr_in6 *)&sa_remote; | 319 | ip6 = (struct sockaddr_in6 *)&sa_remote; |
320 | remote->proto = htons(ETH_P_IPV6); | 320 | remote->proto = htons(ETH_P_IPV6); |
321 | remote->udp_port = ip6->sin6_port; | 321 | remote->port = ip6->sin6_port; |
322 | memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); | 322 | memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
323 | return 0; | 323 | return 0; |
324 | #endif | 324 | #endif |
@@ -386,7 +386,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, | |||
386 | err = -EAFNOSUPPORT; | 386 | err = -EAFNOSUPPORT; |
387 | goto err; | 387 | goto err; |
388 | } | 388 | } |
389 | udp_conf.local_udp_port = local.udp_port; | 389 | udp_conf.local_udp_port = local.port; |
390 | err = udp_sock_create(net, &udp_conf, &ub->ubsock); | 390 | err = udp_sock_create(net, &udp_conf, &ub->ubsock); |
391 | if (err) | 391 | if (err) |
392 | goto err; | 392 | goto err; |