diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/addr.c | 7 | ||||
| -rw-r--r-- | net/tipc/addr.h | 8 | ||||
| -rw-r--r-- | net/tipc/bcast.c | 46 | ||||
| -rw-r--r-- | net/tipc/bcast.h | 1 | ||||
| -rw-r--r-- | net/tipc/bearer.c | 20 | ||||
| -rw-r--r-- | net/tipc/bearer.h | 2 | ||||
| -rw-r--r-- | net/tipc/core.c | 4 | ||||
| -rw-r--r-- | net/tipc/core.h | 37 | ||||
| -rw-r--r-- | net/tipc/link.c | 313 | ||||
| -rw-r--r-- | net/tipc/link.h | 60 | ||||
| -rw-r--r-- | net/tipc/msg.c | 51 | ||||
| -rw-r--r-- | net/tipc/msg.h | 37 | ||||
| -rw-r--r-- | net/tipc/name_table.c | 34 | ||||
| -rw-r--r-- | net/tipc/net.c | 1 | ||||
| -rw-r--r-- | net/tipc/netlink_compat.c | 137 | ||||
| -rw-r--r-- | net/tipc/node.c | 3 | ||||
| -rw-r--r-- | net/tipc/node.h | 2 | ||||
| -rw-r--r-- | net/tipc/server.c | 6 | ||||
| -rw-r--r-- | net/tipc/socket.c | 10 | ||||
| -rw-r--r-- | net/tipc/subscr.c | 242 | ||||
| -rw-r--r-- | net/tipc/subscr.h | 18 |
21 files changed, 546 insertions, 493 deletions
diff --git a/net/tipc/addr.c b/net/tipc/addr.c index ba7daa864d44..48fd3b5a73fb 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c | |||
| @@ -38,13 +38,6 @@ | |||
| 38 | #include "addr.h" | 38 | #include "addr.h" |
| 39 | #include "core.h" | 39 | #include "core.h" |
| 40 | 40 | ||
| 41 | u32 tipc_own_addr(struct net *net) | ||
| 42 | { | ||
| 43 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
| 44 | |||
| 45 | return tn->own_addr; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | 41 | /** |
| 49 | * in_own_cluster - test for cluster inclusion; <0.0.0> always matches | 42 | * in_own_cluster - test for cluster inclusion; <0.0.0> always matches |
| 50 | */ | 43 | */ |
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 7ba6d5c8ae40..93f7c983be33 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
| @@ -41,10 +41,18 @@ | |||
| 41 | #include <linux/tipc.h> | 41 | #include <linux/tipc.h> |
| 42 | #include <net/net_namespace.h> | 42 | #include <net/net_namespace.h> |
| 43 | #include <net/netns/generic.h> | 43 | #include <net/netns/generic.h> |
| 44 | #include "core.h" | ||
| 44 | 45 | ||
| 45 | #define TIPC_ZONE_MASK 0xff000000u | 46 | #define TIPC_ZONE_MASK 0xff000000u |
| 46 | #define TIPC_CLUSTER_MASK 0xfffff000u | 47 | #define TIPC_CLUSTER_MASK 0xfffff000u |
| 47 | 48 | ||
| 49 | static inline u32 tipc_own_addr(struct net *net) | ||
| 50 | { | ||
| 51 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
| 52 | |||
| 53 | return tn->own_addr; | ||
| 54 | } | ||
| 55 | |||
| 48 | static inline u32 tipc_zone_mask(u32 addr) | 56 | static inline u32 tipc_zone_mask(u32 addr) |
| 49 | { | 57 | { |
| 50 | return addr & TIPC_ZONE_MASK; | 58 | return addr & TIPC_ZONE_MASK; |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index c5cbdcb1f0b5..a816382fc8af 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -108,6 +108,11 @@ void tipc_bclink_remove_node(struct net *net, u32 addr) | |||
| 108 | 108 | ||
| 109 | tipc_bclink_lock(net); | 109 | tipc_bclink_lock(net); |
| 110 | tipc_nmap_remove(&tn->bclink->bcast_nodes, addr); | 110 | tipc_nmap_remove(&tn->bclink->bcast_nodes, addr); |
| 111 | |||
| 112 | /* Last node? => reset backlog queue */ | ||
| 113 | if (!tn->bclink->bcast_nodes.count) | ||
| 114 | tipc_link_purge_backlog(&tn->bclink->link); | ||
| 115 | |||
| 111 | tipc_bclink_unlock(net); | 116 | tipc_bclink_unlock(net); |
| 112 | } | 117 | } |
| 113 | 118 | ||
| @@ -115,19 +120,15 @@ static void bclink_set_last_sent(struct net *net) | |||
| 115 | { | 120 | { |
| 116 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 121 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 117 | struct tipc_link *bcl = tn->bcl; | 122 | struct tipc_link *bcl = tn->bcl; |
| 118 | struct sk_buff *skb = skb_peek(&bcl->backlogq); | ||
| 119 | 123 | ||
| 120 | if (skb) | 124 | bcl->silent_intv_cnt = mod(bcl->snd_nxt - 1); |
| 121 | bcl->fsm_msg_cnt = mod(buf_seqno(skb) - 1); | ||
| 122 | else | ||
| 123 | bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1); | ||
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | u32 tipc_bclink_get_last_sent(struct net *net) | 127 | u32 tipc_bclink_get_last_sent(struct net *net) |
| 127 | { | 128 | { |
| 128 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 129 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 129 | 130 | ||
| 130 | return tn->bcl->fsm_msg_cnt; | 131 | return tn->bcl->silent_intv_cnt; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) | 134 | static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) |
| @@ -212,16 +213,16 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) | |||
| 212 | * or both sent and unsent messages (otherwise) | 213 | * or both sent and unsent messages (otherwise) |
| 213 | */ | 214 | */ |
| 214 | if (tn->bclink->bcast_nodes.count) | 215 | if (tn->bclink->bcast_nodes.count) |
| 215 | acked = tn->bcl->fsm_msg_cnt; | 216 | acked = tn->bcl->silent_intv_cnt; |
| 216 | else | 217 | else |
| 217 | acked = tn->bcl->next_out_no; | 218 | acked = tn->bcl->snd_nxt; |
| 218 | } else { | 219 | } else { |
| 219 | /* | 220 | /* |
| 220 | * Bail out if specified sequence number does not correspond | 221 | * Bail out if specified sequence number does not correspond |
| 221 | * to a message that has been sent and not yet acknowledged | 222 | * to a message that has been sent and not yet acknowledged |
| 222 | */ | 223 | */ |
| 223 | if (less(acked, buf_seqno(skb)) || | 224 | if (less(acked, buf_seqno(skb)) || |
| 224 | less(tn->bcl->fsm_msg_cnt, acked) || | 225 | less(tn->bcl->silent_intv_cnt, acked) || |
| 225 | less_eq(acked, n_ptr->bclink.acked)) | 226 | less_eq(acked, n_ptr->bclink.acked)) |
| 226 | goto exit; | 227 | goto exit; |
| 227 | } | 228 | } |
| @@ -803,9 +804,9 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) | |||
| 803 | goto attr_msg_full; | 804 | goto attr_msg_full; |
| 804 | if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name)) | 805 | if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name)) |
| 805 | goto attr_msg_full; | 806 | goto attr_msg_full; |
| 806 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->next_in_no)) | 807 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt)) |
| 807 | goto attr_msg_full; | 808 | goto attr_msg_full; |
| 808 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->next_out_no)) | 809 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt)) |
| 809 | goto attr_msg_full; | 810 | goto attr_msg_full; |
| 810 | 811 | ||
| 811 | prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); | 812 | prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); |
| @@ -866,6 +867,27 @@ int tipc_bclink_set_queue_limits(struct net *net, u32 limit) | |||
| 866 | return 0; | 867 | return 0; |
| 867 | } | 868 | } |
| 868 | 869 | ||
| 870 | int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]) | ||
| 871 | { | ||
| 872 | int err; | ||
| 873 | u32 win; | ||
| 874 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; | ||
| 875 | |||
| 876 | if (!attrs[TIPC_NLA_LINK_PROP]) | ||
| 877 | return -EINVAL; | ||
| 878 | |||
| 879 | err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], props); | ||
| 880 | if (err) | ||
| 881 | return err; | ||
| 882 | |||
| 883 | if (!props[TIPC_NLA_PROP_WIN]) | ||
| 884 | return -EOPNOTSUPP; | ||
| 885 | |||
| 886 | win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); | ||
| 887 | |||
| 888 | return tipc_bclink_set_queue_limits(net, win); | ||
| 889 | } | ||
| 890 | |||
| 869 | int tipc_bclink_init(struct net *net) | 891 | int tipc_bclink_init(struct net *net) |
| 870 | { | 892 | { |
| 871 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 893 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| @@ -893,7 +915,7 @@ int tipc_bclink_init(struct net *net) | |||
| 893 | __skb_queue_head_init(&bcl->backlogq); | 915 | __skb_queue_head_init(&bcl->backlogq); |
| 894 | __skb_queue_head_init(&bcl->deferdq); | 916 | __skb_queue_head_init(&bcl->deferdq); |
| 895 | skb_queue_head_init(&bcl->wakeupq); | 917 | skb_queue_head_init(&bcl->wakeupq); |
| 896 | bcl->next_out_no = 1; | 918 | bcl->snd_nxt = 1; |
| 897 | spin_lock_init(&bclink->node.lock); | 919 | spin_lock_init(&bclink->node.lock); |
| 898 | __skb_queue_head_init(&bclink->arrvq); | 920 | __skb_queue_head_init(&bclink->arrvq); |
| 899 | skb_queue_head_init(&bclink->inputq); | 921 | skb_queue_head_init(&bclink->inputq); |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 4bdc12277d33..3c290a48f720 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
| @@ -131,6 +131,7 @@ uint tipc_bclink_get_mtu(void); | |||
| 131 | int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list); | 131 | int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list); |
| 132 | void tipc_bclink_wakeup_users(struct net *net); | 132 | void tipc_bclink_wakeup_users(struct net *net); |
| 133 | int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); | 133 | int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); |
| 134 | int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]); | ||
| 134 | void tipc_bclink_input(struct net *net); | 135 | void tipc_bclink_input(struct net *net); |
| 135 | 136 | ||
| 136 | #endif | 137 | #endif |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 70e3dacbf84a..00bc0e620532 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -71,8 +71,7 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { | |||
| 71 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } | 71 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, | 74 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr); |
| 75 | bool shutting_down); | ||
| 76 | 75 | ||
| 77 | /** | 76 | /** |
| 78 | * tipc_media_find - locates specified media object by name | 77 | * tipc_media_find - locates specified media object by name |
| @@ -324,7 +323,7 @@ restart: | |||
| 324 | 323 | ||
| 325 | res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); | 324 | res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); |
| 326 | if (res) { | 325 | if (res) { |
| 327 | bearer_disable(net, b_ptr, false); | 326 | bearer_disable(net, b_ptr); |
| 328 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", | 327 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", |
| 329 | name); | 328 | name); |
| 330 | return -EINVAL; | 329 | return -EINVAL; |
| @@ -344,7 +343,7 @@ restart: | |||
| 344 | static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) | 343 | static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) |
| 345 | { | 344 | { |
| 346 | pr_info("Resetting bearer <%s>\n", b_ptr->name); | 345 | pr_info("Resetting bearer <%s>\n", b_ptr->name); |
| 347 | tipc_link_reset_list(net, b_ptr->identity); | 346 | tipc_link_delete_list(net, b_ptr->identity); |
| 348 | tipc_disc_reset(net, b_ptr); | 347 | tipc_disc_reset(net, b_ptr); |
| 349 | return 0; | 348 | return 0; |
| 350 | } | 349 | } |
| @@ -354,8 +353,7 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) | |||
| 354 | * | 353 | * |
| 355 | * Note: This routine assumes caller holds RTNL lock. | 354 | * Note: This routine assumes caller holds RTNL lock. |
| 356 | */ | 355 | */ |
| 357 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, | 356 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr) |
| 358 | bool shutting_down) | ||
| 359 | { | 357 | { |
| 360 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 358 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 361 | u32 i; | 359 | u32 i; |
| @@ -363,7 +361,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, | |||
| 363 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 361 | pr_info("Disabling bearer <%s>\n", b_ptr->name); |
| 364 | b_ptr->media->disable_media(b_ptr); | 362 | b_ptr->media->disable_media(b_ptr); |
| 365 | 363 | ||
| 366 | tipc_link_delete_list(net, b_ptr->identity, shutting_down); | 364 | tipc_link_delete_list(net, b_ptr->identity); |
| 367 | if (b_ptr->link_req) | 365 | if (b_ptr->link_req) |
| 368 | tipc_disc_delete(b_ptr->link_req); | 366 | tipc_disc_delete(b_ptr->link_req); |
| 369 | 367 | ||
| @@ -541,7 +539,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 541 | break; | 539 | break; |
| 542 | case NETDEV_UNREGISTER: | 540 | case NETDEV_UNREGISTER: |
| 543 | case NETDEV_CHANGENAME: | 541 | case NETDEV_CHANGENAME: |
| 544 | bearer_disable(dev_net(dev), b_ptr, false); | 542 | bearer_disable(dev_net(dev), b_ptr); |
| 545 | break; | 543 | break; |
| 546 | } | 544 | } |
| 547 | return NOTIFY_OK; | 545 | return NOTIFY_OK; |
| @@ -583,7 +581,7 @@ void tipc_bearer_stop(struct net *net) | |||
| 583 | for (i = 0; i < MAX_BEARERS; i++) { | 581 | for (i = 0; i < MAX_BEARERS; i++) { |
| 584 | b_ptr = rtnl_dereference(tn->bearer_list[i]); | 582 | b_ptr = rtnl_dereference(tn->bearer_list[i]); |
| 585 | if (b_ptr) { | 583 | if (b_ptr) { |
| 586 | bearer_disable(net, b_ptr, true); | 584 | bearer_disable(net, b_ptr); |
| 587 | tn->bearer_list[i] = NULL; | 585 | tn->bearer_list[i] = NULL; |
| 588 | } | 586 | } |
| 589 | } | 587 | } |
| @@ -747,7 +745,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) | |||
| 747 | return -EINVAL; | 745 | return -EINVAL; |
| 748 | } | 746 | } |
| 749 | 747 | ||
| 750 | bearer_disable(net, bearer, false); | 748 | bearer_disable(net, bearer); |
| 751 | rtnl_unlock(); | 749 | rtnl_unlock(); |
| 752 | 750 | ||
| 753 | return 0; | 751 | return 0; |
| @@ -812,7 +810,7 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) | |||
| 812 | char *name; | 810 | char *name; |
| 813 | struct tipc_bearer *b; | 811 | struct tipc_bearer *b; |
| 814 | struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; | 812 | struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; |
| 815 | struct net *net = genl_info_net(info); | 813 | struct net *net = sock_net(skb->sk); |
| 816 | 814 | ||
| 817 | if (!info->attrs[TIPC_NLA_BEARER]) | 815 | if (!info->attrs[TIPC_NLA_BEARER]) |
| 818 | return -EINVAL; | 816 | return -EINVAL; |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 5cad243ee8fc..dc714d977768 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
| @@ -38,9 +38,9 @@ | |||
| 38 | #define _TIPC_BEARER_H | 38 | #define _TIPC_BEARER_H |
| 39 | 39 | ||
| 40 | #include "netlink.h" | 40 | #include "netlink.h" |
| 41 | #include "core.h" | ||
| 41 | #include <net/genetlink.h> | 42 | #include <net/genetlink.h> |
| 42 | 43 | ||
| 43 | #define MAX_BEARERS 2 | ||
| 44 | #define MAX_MEDIA 3 | 44 | #define MAX_MEDIA 3 |
| 45 | #define MAX_NODES 4096 | 45 | #define MAX_NODES 4096 |
| 46 | #define WSIZE 32 | 46 | #define WSIZE 32 |
diff --git a/net/tipc/core.c b/net/tipc/core.c index be1c9fa60b09..005ba5eb0ea4 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
| @@ -68,7 +68,7 @@ static int __net_init tipc_init_net(struct net *net) | |||
| 68 | if (err) | 68 | if (err) |
| 69 | goto out_nametbl; | 69 | goto out_nametbl; |
| 70 | 70 | ||
| 71 | err = tipc_subscr_start(net); | 71 | err = tipc_topsrv_start(net); |
| 72 | if (err) | 72 | if (err) |
| 73 | goto out_subscr; | 73 | goto out_subscr; |
| 74 | return 0; | 74 | return 0; |
| @@ -83,7 +83,7 @@ out_sk_rht: | |||
| 83 | 83 | ||
| 84 | static void __net_exit tipc_exit_net(struct net *net) | 84 | static void __net_exit tipc_exit_net(struct net *net) |
| 85 | { | 85 | { |
| 86 | tipc_subscr_stop(net); | 86 | tipc_topsrv_stop(net); |
| 87 | tipc_net_stop(net); | 87 | tipc_net_stop(net); |
| 88 | tipc_nametbl_stop(net); | 88 | tipc_nametbl_stop(net); |
| 89 | tipc_sk_rht_destroy(net); | 89 | tipc_sk_rht_destroy(net); |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 3dc68c7a966d..0fcf133d5cb7 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
| @@ -60,16 +60,19 @@ | |||
| 60 | #include <net/netns/generic.h> | 60 | #include <net/netns/generic.h> |
| 61 | #include <linux/rhashtable.h> | 61 | #include <linux/rhashtable.h> |
| 62 | 62 | ||
| 63 | #include "node.h" | 63 | struct tipc_node; |
| 64 | #include "bearer.h" | 64 | struct tipc_bearer; |
| 65 | #include "bcast.h" | 65 | struct tipc_bcbearer; |
| 66 | #include "netlink.h" | 66 | struct tipc_bclink; |
| 67 | #include "link.h" | 67 | struct tipc_link; |
| 68 | #include "node.h" | 68 | struct tipc_name_table; |
| 69 | #include "msg.h" | 69 | struct tipc_server; |
| 70 | 70 | ||
| 71 | #define TIPC_MOD_VER "2.0.0" | 71 | #define TIPC_MOD_VER "2.0.0" |
| 72 | 72 | ||
| 73 | #define NODE_HTABLE_SIZE 512 | ||
| 74 | #define MAX_BEARERS 3 | ||
| 75 | |||
| 73 | extern int tipc_net_id __read_mostly; | 76 | extern int tipc_net_id __read_mostly; |
| 74 | extern int sysctl_tipc_rmem[3] __read_mostly; | 77 | extern int sysctl_tipc_rmem[3] __read_mostly; |
| 75 | extern int sysctl_tipc_named_timeout __read_mostly; | 78 | extern int sysctl_tipc_named_timeout __read_mostly; |
| @@ -106,6 +109,26 @@ struct tipc_net { | |||
| 106 | atomic_t subscription_count; | 109 | atomic_t subscription_count; |
| 107 | }; | 110 | }; |
| 108 | 111 | ||
| 112 | static inline u16 mod(u16 x) | ||
| 113 | { | ||
| 114 | return x & 0xffffu; | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline int less_eq(u16 left, u16 right) | ||
| 118 | { | ||
| 119 | return mod(right - left) < 32768u; | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline int more(u16 left, u16 right) | ||
| 123 | { | ||
| 124 | return !less_eq(left, right); | ||
| 125 | } | ||
| 126 | |||
| 127 | static inline int less(u16 left, u16 right) | ||
| 128 | { | ||
| 129 | return less_eq(left, right) && (mod(right) != mod(left)); | ||
| 130 | } | ||
| 131 | |||
| 109 | #ifdef CONFIG_SYSCTL | 132 | #ifdef CONFIG_SYSCTL |
| 110 | int tipc_register_sysctl(void); | 133 | int tipc_register_sysctl(void); |
| 111 | void tipc_unregister_sysctl(void); | 134 | void tipc_unregister_sysctl(void); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 43a515dc97b0..eaa9fe54b4ae 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -86,7 +86,7 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | |||
| 86 | */ | 86 | */ |
| 87 | #define STARTING_EVT 856384768 /* link processing trigger */ | 87 | #define STARTING_EVT 856384768 /* link processing trigger */ |
| 88 | #define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ | 88 | #define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ |
| 89 | #define TIMEOUT_EVT 560817u /* link timer expired */ | 89 | #define SILENCE_EVT 560817u /* timer dicovered silence from peer */ |
| 90 | 90 | ||
| 91 | /* | 91 | /* |
| 92 | * State value stored in 'failover_pkts' | 92 | * State value stored in 'failover_pkts' |
| @@ -106,6 +106,7 @@ static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); | |||
| 106 | static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb); | 106 | static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb); |
| 107 | static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb); | 107 | static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb); |
| 108 | static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb); | 108 | static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb); |
| 109 | static void link_set_timer(struct tipc_link *link, unsigned long time); | ||
| 109 | /* | 110 | /* |
| 110 | * Simple link routines | 111 | * Simple link routines |
| 111 | */ | 112 | */ |
| @@ -197,11 +198,12 @@ static void link_timeout(unsigned long data) | |||
| 197 | } | 198 | } |
| 198 | 199 | ||
| 199 | /* do all other link processing performed on a periodic basis */ | 200 | /* do all other link processing performed on a periodic basis */ |
| 200 | link_state_event(l_ptr, TIMEOUT_EVT); | 201 | if (l_ptr->silent_intv_cnt || tipc_bclink_acks_missing(l_ptr->owner)) |
| 201 | 202 | link_state_event(l_ptr, SILENCE_EVT); | |
| 203 | l_ptr->silent_intv_cnt++; | ||
| 202 | if (skb_queue_len(&l_ptr->backlogq)) | 204 | if (skb_queue_len(&l_ptr->backlogq)) |
| 203 | tipc_link_push_packets(l_ptr); | 205 | tipc_link_push_packets(l_ptr); |
| 204 | 206 | link_set_timer(l_ptr, l_ptr->keepalive_intv); | |
| 205 | tipc_node_unlock(l_ptr->owner); | 207 | tipc_node_unlock(l_ptr->owner); |
| 206 | tipc_link_put(l_ptr); | 208 | tipc_link_put(l_ptr); |
| 207 | } | 209 | } |
| @@ -233,8 +235,8 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 233 | 235 | ||
| 234 | if (n_ptr->link_cnt >= MAX_BEARERS) { | 236 | if (n_ptr->link_cnt >= MAX_BEARERS) { |
| 235 | tipc_addr_string_fill(addr_string, n_ptr->addr); | 237 | tipc_addr_string_fill(addr_string, n_ptr->addr); |
| 236 | pr_err("Attempt to establish %uth link to %s. Max %u allowed.\n", | 238 | pr_err("Cannot establish %uth link to %s. Max %u allowed.\n", |
| 237 | n_ptr->link_cnt, addr_string, MAX_BEARERS); | 239 | n_ptr->link_cnt, addr_string, MAX_BEARERS); |
| 238 | return NULL; | 240 | return NULL; |
| 239 | } | 241 | } |
| 240 | 242 | ||
| @@ -261,7 +263,6 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 261 | /* note: peer i/f name is updated by reset/activate message */ | 263 | /* note: peer i/f name is updated by reset/activate message */ |
| 262 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); | 264 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); |
| 263 | l_ptr->owner = n_ptr; | 265 | l_ptr->owner = n_ptr; |
| 264 | l_ptr->checkpoint = 1; | ||
| 265 | l_ptr->peer_session = INVALID_SESSION; | 266 | l_ptr->peer_session = INVALID_SESSION; |
| 266 | l_ptr->bearer_id = b_ptr->identity; | 267 | l_ptr->bearer_id = b_ptr->identity; |
| 267 | link_set_supervision_props(l_ptr, b_ptr->tolerance); | 268 | link_set_supervision_props(l_ptr, b_ptr->tolerance); |
| @@ -280,7 +281,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 280 | l_ptr->mtu = l_ptr->advertised_mtu; | 281 | l_ptr->mtu = l_ptr->advertised_mtu; |
| 281 | l_ptr->priority = b_ptr->priority; | 282 | l_ptr->priority = b_ptr->priority; |
| 282 | tipc_link_set_queue_limits(l_ptr, b_ptr->window); | 283 | tipc_link_set_queue_limits(l_ptr, b_ptr->window); |
| 283 | l_ptr->next_out_no = 1; | 284 | l_ptr->snd_nxt = 1; |
| 284 | __skb_queue_head_init(&l_ptr->transmq); | 285 | __skb_queue_head_init(&l_ptr->transmq); |
| 285 | __skb_queue_head_init(&l_ptr->backlogq); | 286 | __skb_queue_head_init(&l_ptr->backlogq); |
| 286 | __skb_queue_head_init(&l_ptr->deferdq); | 287 | __skb_queue_head_init(&l_ptr->deferdq); |
| @@ -311,8 +312,7 @@ void tipc_link_delete(struct tipc_link *l) | |||
| 311 | tipc_link_put(l); | 312 | tipc_link_put(l); |
| 312 | } | 313 | } |
| 313 | 314 | ||
| 314 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id, | 315 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id) |
| 315 | bool shutting_down) | ||
| 316 | { | 316 | { |
| 317 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 317 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 318 | struct tipc_link *link; | 318 | struct tipc_link *link; |
| @@ -404,7 +404,7 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr) | |||
| 404 | l_ptr->reasm_buf = NULL; | 404 | l_ptr->reasm_buf = NULL; |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | static void tipc_link_purge_backlog(struct tipc_link *l) | 407 | void tipc_link_purge_backlog(struct tipc_link *l) |
| 408 | { | 408 | { |
| 409 | __skb_queue_purge(&l->backlogq); | 409 | __skb_queue_purge(&l->backlogq); |
| 410 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; | 410 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; |
| @@ -451,9 +451,9 @@ void tipc_link_reset(struct tipc_link *l_ptr) | |||
| 451 | 451 | ||
| 452 | if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) { | 452 | if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) { |
| 453 | l_ptr->flags |= LINK_FAILINGOVER; | 453 | l_ptr->flags |= LINK_FAILINGOVER; |
| 454 | l_ptr->failover_checkpt = l_ptr->next_in_no; | 454 | l_ptr->failover_checkpt = l_ptr->rcv_nxt; |
| 455 | pl->failover_pkts = FIRST_FAILOVER; | 455 | pl->failover_pkts = FIRST_FAILOVER; |
| 456 | pl->failover_checkpt = l_ptr->next_in_no; | 456 | pl->failover_checkpt = l_ptr->rcv_nxt; |
| 457 | pl->failover_skb = l_ptr->reasm_buf; | 457 | pl->failover_skb = l_ptr->reasm_buf; |
| 458 | } else { | 458 | } else { |
| 459 | kfree_skb(l_ptr->reasm_buf); | 459 | kfree_skb(l_ptr->reasm_buf); |
| @@ -469,36 +469,19 @@ void tipc_link_reset(struct tipc_link *l_ptr) | |||
| 469 | tipc_link_purge_backlog(l_ptr); | 469 | tipc_link_purge_backlog(l_ptr); |
| 470 | l_ptr->reasm_buf = NULL; | 470 | l_ptr->reasm_buf = NULL; |
| 471 | l_ptr->rcv_unacked = 0; | 471 | l_ptr->rcv_unacked = 0; |
| 472 | l_ptr->checkpoint = 1; | 472 | l_ptr->snd_nxt = 1; |
| 473 | l_ptr->next_out_no = 1; | 473 | l_ptr->silent_intv_cnt = 0; |
| 474 | l_ptr->fsm_msg_cnt = 0; | ||
| 475 | l_ptr->stale_count = 0; | 474 | l_ptr->stale_count = 0; |
| 476 | link_reset_statistics(l_ptr); | 475 | link_reset_statistics(l_ptr); |
| 477 | } | 476 | } |
| 478 | 477 | ||
| 479 | void tipc_link_reset_list(struct net *net, unsigned int bearer_id) | ||
| 480 | { | ||
| 481 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
| 482 | struct tipc_link *l_ptr; | ||
| 483 | struct tipc_node *n_ptr; | ||
| 484 | |||
| 485 | rcu_read_lock(); | ||
| 486 | list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { | ||
| 487 | tipc_node_lock(n_ptr); | ||
| 488 | l_ptr = n_ptr->links[bearer_id]; | ||
| 489 | if (l_ptr) | ||
| 490 | tipc_link_reset(l_ptr); | ||
| 491 | tipc_node_unlock(n_ptr); | ||
| 492 | } | ||
| 493 | rcu_read_unlock(); | ||
| 494 | } | ||
| 495 | |||
| 496 | static void link_activate(struct tipc_link *link) | 478 | static void link_activate(struct tipc_link *link) |
| 497 | { | 479 | { |
| 498 | struct tipc_node *node = link->owner; | 480 | struct tipc_node *node = link->owner; |
| 499 | 481 | ||
| 500 | link->next_in_no = 1; | 482 | link->rcv_nxt = 1; |
| 501 | link->stats.recv_info = 1; | 483 | link->stats.recv_info = 1; |
| 484 | link->silent_intv_cnt = 0; | ||
| 502 | tipc_node_link_up(node, link); | 485 | tipc_node_link_up(node, link); |
| 503 | tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); | 486 | tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); |
| 504 | } | 487 | } |
| @@ -511,7 +494,7 @@ static void link_activate(struct tipc_link *link) | |||
| 511 | static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | 494 | static void link_state_event(struct tipc_link *l_ptr, unsigned int event) |
| 512 | { | 495 | { |
| 513 | struct tipc_link *other; | 496 | struct tipc_link *other; |
| 514 | unsigned long cont_intv = l_ptr->cont_intv; | 497 | unsigned long timer_intv = l_ptr->keepalive_intv; |
| 515 | 498 | ||
| 516 | if (l_ptr->flags & LINK_STOPPED) | 499 | if (l_ptr->flags & LINK_STOPPED) |
| 517 | return; | 500 | return; |
| @@ -519,45 +502,33 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 519 | if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) | 502 | if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) |
| 520 | return; /* Not yet. */ | 503 | return; /* Not yet. */ |
| 521 | 504 | ||
| 522 | if (l_ptr->flags & LINK_FAILINGOVER) { | 505 | if (l_ptr->flags & LINK_FAILINGOVER) |
| 523 | if (event == TIMEOUT_EVT) | ||
| 524 | link_set_timer(l_ptr, cont_intv); | ||
| 525 | return; | 506 | return; |
| 526 | } | ||
| 527 | 507 | ||
| 528 | switch (l_ptr->state) { | 508 | switch (l_ptr->state) { |
| 529 | case WORKING_WORKING: | 509 | case WORKING_WORKING: |
| 530 | switch (event) { | 510 | switch (event) { |
| 531 | case TRAFFIC_MSG_EVT: | 511 | case TRAFFIC_MSG_EVT: |
| 532 | case ACTIVATE_MSG: | 512 | case ACTIVATE_MSG: |
| 513 | l_ptr->silent_intv_cnt = 0; | ||
| 533 | break; | 514 | break; |
| 534 | case TIMEOUT_EVT: | 515 | case SILENCE_EVT: |
| 535 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | 516 | if (!l_ptr->silent_intv_cnt) { |
| 536 | l_ptr->checkpoint = l_ptr->next_in_no; | 517 | if (tipc_bclink_acks_missing(l_ptr->owner)) |
| 537 | if (tipc_bclink_acks_missing(l_ptr->owner)) { | ||
| 538 | tipc_link_proto_xmit(l_ptr, STATE_MSG, | 518 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 539 | 0, 0, 0, 0); | 519 | 0, 0, 0, 0); |
| 540 | l_ptr->fsm_msg_cnt++; | ||
| 541 | } | ||
| 542 | link_set_timer(l_ptr, cont_intv); | ||
| 543 | break; | 520 | break; |
| 544 | } | 521 | } |
| 545 | l_ptr->state = WORKING_UNKNOWN; | 522 | l_ptr->state = WORKING_UNKNOWN; |
| 546 | l_ptr->fsm_msg_cnt = 0; | ||
| 547 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); | 523 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); |
| 548 | l_ptr->fsm_msg_cnt++; | ||
| 549 | link_set_timer(l_ptr, cont_intv / 4); | ||
| 550 | break; | 524 | break; |
| 551 | case RESET_MSG: | 525 | case RESET_MSG: |
| 552 | pr_debug("%s<%s>, requested by peer\n", | 526 | pr_debug("%s<%s>, requested by peer\n", |
| 553 | link_rst_msg, l_ptr->name); | 527 | link_rst_msg, l_ptr->name); |
| 554 | tipc_link_reset(l_ptr); | 528 | tipc_link_reset(l_ptr); |
| 555 | l_ptr->state = RESET_RESET; | 529 | l_ptr->state = RESET_RESET; |
| 556 | l_ptr->fsm_msg_cnt = 0; | ||
| 557 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, | 530 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 558 | 0, 0, 0, 0); | 531 | 0, 0, 0, 0); |
| 559 | l_ptr->fsm_msg_cnt++; | ||
| 560 | link_set_timer(l_ptr, cont_intv); | ||
| 561 | break; | 532 | break; |
| 562 | default: | 533 | default: |
| 563 | pr_debug("%s%u in WW state\n", link_unk_evt, event); | 534 | pr_debug("%s%u in WW state\n", link_unk_evt, event); |
| @@ -568,46 +539,33 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 568 | case TRAFFIC_MSG_EVT: | 539 | case TRAFFIC_MSG_EVT: |
| 569 | case ACTIVATE_MSG: | 540 | case ACTIVATE_MSG: |
| 570 | l_ptr->state = WORKING_WORKING; | 541 | l_ptr->state = WORKING_WORKING; |
| 571 | l_ptr->fsm_msg_cnt = 0; | 542 | l_ptr->silent_intv_cnt = 0; |
| 572 | link_set_timer(l_ptr, cont_intv); | ||
| 573 | break; | 543 | break; |
| 574 | case RESET_MSG: | 544 | case RESET_MSG: |
| 575 | pr_debug("%s<%s>, requested by peer while probing\n", | 545 | pr_debug("%s<%s>, requested by peer while probing\n", |
| 576 | link_rst_msg, l_ptr->name); | 546 | link_rst_msg, l_ptr->name); |
| 577 | tipc_link_reset(l_ptr); | 547 | tipc_link_reset(l_ptr); |
| 578 | l_ptr->state = RESET_RESET; | 548 | l_ptr->state = RESET_RESET; |
| 579 | l_ptr->fsm_msg_cnt = 0; | ||
| 580 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, | 549 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 581 | 0, 0, 0, 0); | 550 | 0, 0, 0, 0); |
| 582 | l_ptr->fsm_msg_cnt++; | ||
| 583 | link_set_timer(l_ptr, cont_intv); | ||
| 584 | break; | 551 | break; |
| 585 | case TIMEOUT_EVT: | 552 | case SILENCE_EVT: |
| 586 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | 553 | if (!l_ptr->silent_intv_cnt) { |
| 587 | l_ptr->state = WORKING_WORKING; | 554 | l_ptr->state = WORKING_WORKING; |
| 588 | l_ptr->fsm_msg_cnt = 0; | 555 | if (tipc_bclink_acks_missing(l_ptr->owner)) |
| 589 | l_ptr->checkpoint = l_ptr->next_in_no; | ||
| 590 | if (tipc_bclink_acks_missing(l_ptr->owner)) { | ||
| 591 | tipc_link_proto_xmit(l_ptr, STATE_MSG, | 556 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 592 | 0, 0, 0, 0); | 557 | 0, 0, 0, 0); |
| 593 | l_ptr->fsm_msg_cnt++; | 558 | } else if (l_ptr->silent_intv_cnt < |
| 594 | } | 559 | l_ptr->abort_limit) { |
| 595 | link_set_timer(l_ptr, cont_intv); | ||
| 596 | } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { | ||
| 597 | tipc_link_proto_xmit(l_ptr, STATE_MSG, | 560 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 598 | 1, 0, 0, 0); | 561 | 1, 0, 0, 0); |
| 599 | l_ptr->fsm_msg_cnt++; | ||
| 600 | link_set_timer(l_ptr, cont_intv / 4); | ||
| 601 | } else { /* Link has failed */ | 562 | } else { /* Link has failed */ |
| 602 | pr_debug("%s<%s>, peer not responding\n", | 563 | pr_debug("%s<%s>, peer not responding\n", |
| 603 | link_rst_msg, l_ptr->name); | 564 | link_rst_msg, l_ptr->name); |
| 604 | tipc_link_reset(l_ptr); | 565 | tipc_link_reset(l_ptr); |
| 605 | l_ptr->state = RESET_UNKNOWN; | 566 | l_ptr->state = RESET_UNKNOWN; |
| 606 | l_ptr->fsm_msg_cnt = 0; | ||
| 607 | tipc_link_proto_xmit(l_ptr, RESET_MSG, | 567 | tipc_link_proto_xmit(l_ptr, RESET_MSG, |
| 608 | 0, 0, 0, 0); | 568 | 0, 0, 0, 0); |
| 609 | l_ptr->fsm_msg_cnt++; | ||
| 610 | link_set_timer(l_ptr, cont_intv); | ||
| 611 | } | 569 | } |
| 612 | break; | 570 | break; |
| 613 | default: | 571 | default: |
| @@ -623,31 +581,22 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 623 | if (other && link_working_unknown(other)) | 581 | if (other && link_working_unknown(other)) |
| 624 | break; | 582 | break; |
| 625 | l_ptr->state = WORKING_WORKING; | 583 | l_ptr->state = WORKING_WORKING; |
| 626 | l_ptr->fsm_msg_cnt = 0; | ||
| 627 | link_activate(l_ptr); | 584 | link_activate(l_ptr); |
| 628 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); | 585 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); |
| 629 | l_ptr->fsm_msg_cnt++; | ||
| 630 | if (l_ptr->owner->working_links == 1) | 586 | if (l_ptr->owner->working_links == 1) |
| 631 | tipc_link_sync_xmit(l_ptr); | 587 | tipc_link_sync_xmit(l_ptr); |
| 632 | link_set_timer(l_ptr, cont_intv); | ||
| 633 | break; | 588 | break; |
| 634 | case RESET_MSG: | 589 | case RESET_MSG: |
| 635 | l_ptr->state = RESET_RESET; | 590 | l_ptr->state = RESET_RESET; |
| 636 | l_ptr->fsm_msg_cnt = 0; | ||
| 637 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, | 591 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 638 | 1, 0, 0, 0); | 592 | 1, 0, 0, 0); |
| 639 | l_ptr->fsm_msg_cnt++; | ||
| 640 | link_set_timer(l_ptr, cont_intv); | ||
| 641 | break; | 593 | break; |
| 642 | case STARTING_EVT: | 594 | case STARTING_EVT: |
| 643 | l_ptr->flags |= LINK_STARTED; | 595 | l_ptr->flags |= LINK_STARTED; |
| 644 | l_ptr->fsm_msg_cnt++; | 596 | link_set_timer(l_ptr, timer_intv); |
| 645 | link_set_timer(l_ptr, cont_intv); | ||
| 646 | break; | 597 | break; |
| 647 | case TIMEOUT_EVT: | 598 | case SILENCE_EVT: |
| 648 | tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0); | 599 | tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0); |
| 649 | l_ptr->fsm_msg_cnt++; | ||
| 650 | link_set_timer(l_ptr, cont_intv); | ||
| 651 | break; | 600 | break; |
| 652 | default: | 601 | default: |
| 653 | pr_err("%s%u in RU state\n", link_unk_evt, event); | 602 | pr_err("%s%u in RU state\n", link_unk_evt, event); |
| @@ -661,21 +610,16 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 661 | if (other && link_working_unknown(other)) | 610 | if (other && link_working_unknown(other)) |
| 662 | break; | 611 | break; |
| 663 | l_ptr->state = WORKING_WORKING; | 612 | l_ptr->state = WORKING_WORKING; |
| 664 | l_ptr->fsm_msg_cnt = 0; | ||
| 665 | link_activate(l_ptr); | 613 | link_activate(l_ptr); |
| 666 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); | 614 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); |
| 667 | l_ptr->fsm_msg_cnt++; | ||
| 668 | if (l_ptr->owner->working_links == 1) | 615 | if (l_ptr->owner->working_links == 1) |
| 669 | tipc_link_sync_xmit(l_ptr); | 616 | tipc_link_sync_xmit(l_ptr); |
| 670 | link_set_timer(l_ptr, cont_intv); | ||
| 671 | break; | 617 | break; |
| 672 | case RESET_MSG: | 618 | case RESET_MSG: |
| 673 | break; | 619 | break; |
| 674 | case TIMEOUT_EVT: | 620 | case SILENCE_EVT: |
| 675 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, | 621 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 676 | 0, 0, 0, 0); | 622 | 0, 0, 0, 0); |
| 677 | l_ptr->fsm_msg_cnt++; | ||
| 678 | link_set_timer(l_ptr, cont_intv); | ||
| 679 | break; | 623 | break; |
| 680 | default: | 624 | default: |
| 681 | pr_err("%s%u in RR state\n", link_unk_evt, event); | 625 | pr_err("%s%u in RR state\n", link_unk_evt, event); |
| @@ -701,53 +645,58 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link, | |||
| 701 | { | 645 | { |
| 702 | struct tipc_msg *msg = buf_msg(skb_peek(list)); | 646 | struct tipc_msg *msg = buf_msg(skb_peek(list)); |
| 703 | unsigned int maxwin = link->window; | 647 | unsigned int maxwin = link->window; |
| 704 | unsigned int imp = msg_importance(msg); | 648 | unsigned int i, imp = msg_importance(msg); |
| 705 | uint mtu = link->mtu; | 649 | uint mtu = link->mtu; |
| 706 | uint ack = mod(link->next_in_no - 1); | 650 | u16 ack = mod(link->rcv_nxt - 1); |
| 707 | uint seqno = link->next_out_no; | 651 | u16 seqno = link->snd_nxt; |
| 708 | uint bc_last_in = link->owner->bclink.last_in; | 652 | u16 bc_last_in = link->owner->bclink.last_in; |
| 709 | struct tipc_media_addr *addr = &link->media_addr; | 653 | struct tipc_media_addr *addr = &link->media_addr; |
| 710 | struct sk_buff_head *transmq = &link->transmq; | 654 | struct sk_buff_head *transmq = &link->transmq; |
| 711 | struct sk_buff_head *backlogq = &link->backlogq; | 655 | struct sk_buff_head *backlogq = &link->backlogq; |
| 712 | struct sk_buff *skb, *tmp; | 656 | struct sk_buff *skb, *bskb; |
| 713 | |||
| 714 | /* Match backlog limit against msg importance: */ | ||
| 715 | if (unlikely(link->backlog[imp].len >= link->backlog[imp].limit)) | ||
| 716 | return link_schedule_user(link, list); | ||
| 717 | 657 | ||
| 658 | /* Match msg importance against this and all higher backlog limits: */ | ||
| 659 | for (i = imp; i <= TIPC_SYSTEM_IMPORTANCE; i++) { | ||
| 660 | if (unlikely(link->backlog[i].len >= link->backlog[i].limit)) | ||
| 661 | return link_schedule_user(link, list); | ||
| 662 | } | ||
| 718 | if (unlikely(msg_size(msg) > mtu)) { | 663 | if (unlikely(msg_size(msg) > mtu)) { |
| 719 | __skb_queue_purge(list); | 664 | __skb_queue_purge(list); |
| 720 | return -EMSGSIZE; | 665 | return -EMSGSIZE; |
| 721 | } | 666 | } |
| 722 | /* Prepare each packet for sending, and add to relevant queue: */ | 667 | /* Prepare each packet for sending, and add to relevant queue: */ |
| 723 | skb_queue_walk_safe(list, skb, tmp) { | 668 | while (skb_queue_len(list)) { |
| 724 | __skb_unlink(skb, list); | 669 | skb = skb_peek(list); |
| 725 | msg = buf_msg(skb); | 670 | msg = buf_msg(skb); |
| 726 | msg_set_seqno(msg, seqno); | 671 | msg_set_seqno(msg, seqno); |
| 727 | msg_set_ack(msg, ack); | 672 | msg_set_ack(msg, ack); |
| 728 | msg_set_bcast_ack(msg, bc_last_in); | 673 | msg_set_bcast_ack(msg, bc_last_in); |
| 729 | 674 | ||
| 730 | if (likely(skb_queue_len(transmq) < maxwin)) { | 675 | if (likely(skb_queue_len(transmq) < maxwin)) { |
| 676 | __skb_dequeue(list); | ||
| 731 | __skb_queue_tail(transmq, skb); | 677 | __skb_queue_tail(transmq, skb); |
| 732 | tipc_bearer_send(net, link->bearer_id, skb, addr); | 678 | tipc_bearer_send(net, link->bearer_id, skb, addr); |
| 733 | link->rcv_unacked = 0; | 679 | link->rcv_unacked = 0; |
| 734 | seqno++; | 680 | seqno++; |
| 735 | continue; | 681 | continue; |
| 736 | } | 682 | } |
| 737 | if (tipc_msg_bundle(skb_peek_tail(backlogq), skb, mtu)) { | 683 | if (tipc_msg_bundle(skb_peek_tail(backlogq), msg, mtu)) { |
| 684 | kfree_skb(__skb_dequeue(list)); | ||
| 738 | link->stats.sent_bundled++; | 685 | link->stats.sent_bundled++; |
| 739 | continue; | 686 | continue; |
| 740 | } | 687 | } |
| 741 | if (tipc_msg_make_bundle(&skb, mtu, link->addr)) { | 688 | if (tipc_msg_make_bundle(&bskb, msg, mtu, link->addr)) { |
| 689 | kfree_skb(__skb_dequeue(list)); | ||
| 690 | __skb_queue_tail(backlogq, bskb); | ||
| 691 | link->backlog[msg_importance(buf_msg(bskb))].len++; | ||
| 742 | link->stats.sent_bundled++; | 692 | link->stats.sent_bundled++; |
| 743 | link->stats.sent_bundles++; | 693 | link->stats.sent_bundles++; |
| 744 | imp = msg_importance(buf_msg(skb)); | 694 | continue; |
| 745 | } | 695 | } |
| 746 | __skb_queue_tail(backlogq, skb); | 696 | link->backlog[imp].len += skb_queue_len(list); |
| 747 | link->backlog[imp].len++; | 697 | skb_queue_splice_tail_init(list, backlogq); |
| 748 | seqno++; | ||
| 749 | } | 698 | } |
| 750 | link->next_out_no = seqno; | 699 | link->snd_nxt = seqno; |
| 751 | return 0; | 700 | return 0; |
| 752 | } | 701 | } |
| 753 | 702 | ||
| @@ -877,7 +826,8 @@ void tipc_link_push_packets(struct tipc_link *link) | |||
| 877 | { | 826 | { |
| 878 | struct sk_buff *skb; | 827 | struct sk_buff *skb; |
| 879 | struct tipc_msg *msg; | 828 | struct tipc_msg *msg; |
| 880 | unsigned int ack = mod(link->next_in_no - 1); | 829 | u16 seqno = link->snd_nxt; |
| 830 | u16 ack = mod(link->rcv_nxt - 1); | ||
| 881 | 831 | ||
| 882 | while (skb_queue_len(&link->transmq) < link->window) { | 832 | while (skb_queue_len(&link->transmq) < link->window) { |
| 883 | skb = __skb_dequeue(&link->backlogq); | 833 | skb = __skb_dequeue(&link->backlogq); |
| @@ -886,12 +836,15 @@ void tipc_link_push_packets(struct tipc_link *link) | |||
| 886 | msg = buf_msg(skb); | 836 | msg = buf_msg(skb); |
| 887 | link->backlog[msg_importance(msg)].len--; | 837 | link->backlog[msg_importance(msg)].len--; |
| 888 | msg_set_ack(msg, ack); | 838 | msg_set_ack(msg, ack); |
| 839 | msg_set_seqno(msg, seqno); | ||
| 840 | seqno = mod(seqno + 1); | ||
| 889 | msg_set_bcast_ack(msg, link->owner->bclink.last_in); | 841 | msg_set_bcast_ack(msg, link->owner->bclink.last_in); |
| 890 | link->rcv_unacked = 0; | 842 | link->rcv_unacked = 0; |
| 891 | __skb_queue_tail(&link->transmq, skb); | 843 | __skb_queue_tail(&link->transmq, skb); |
| 892 | tipc_bearer_send(link->owner->net, link->bearer_id, | 844 | tipc_bearer_send(link->owner->net, link->bearer_id, |
| 893 | skb, &link->media_addr); | 845 | skb, &link->media_addr); |
| 894 | } | 846 | } |
| 847 | link->snd_nxt = seqno; | ||
| 895 | } | 848 | } |
| 896 | 849 | ||
| 897 | void tipc_link_reset_all(struct tipc_node *node) | 850 | void tipc_link_reset_all(struct tipc_node *node) |
| @@ -964,13 +917,13 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb, | |||
| 964 | msg = buf_msg(skb); | 917 | msg = buf_msg(skb); |
| 965 | 918 | ||
| 966 | /* Detect repeated retransmit failures */ | 919 | /* Detect repeated retransmit failures */ |
| 967 | if (l_ptr->last_retransmitted == msg_seqno(msg)) { | 920 | if (l_ptr->last_retransm == msg_seqno(msg)) { |
| 968 | if (++l_ptr->stale_count > 100) { | 921 | if (++l_ptr->stale_count > 100) { |
| 969 | link_retransmit_failure(l_ptr, skb); | 922 | link_retransmit_failure(l_ptr, skb); |
| 970 | return; | 923 | return; |
| 971 | } | 924 | } |
| 972 | } else { | 925 | } else { |
| 973 | l_ptr->last_retransmitted = msg_seqno(msg); | 926 | l_ptr->last_retransm = msg_seqno(msg); |
| 974 | l_ptr->stale_count = 1; | 927 | l_ptr->stale_count = 1; |
| 975 | } | 928 | } |
| 976 | 929 | ||
| @@ -978,7 +931,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb, | |||
| 978 | if (!retransmits) | 931 | if (!retransmits) |
| 979 | break; | 932 | break; |
| 980 | msg = buf_msg(skb); | 933 | msg = buf_msg(skb); |
| 981 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 934 | msg_set_ack(msg, mod(l_ptr->rcv_nxt - 1)); |
| 982 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 935 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
| 983 | tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, skb, | 936 | tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, skb, |
| 984 | &l_ptr->media_addr); | 937 | &l_ptr->media_addr); |
| @@ -1001,11 +954,11 @@ static bool link_synch(struct tipc_link *l) | |||
| 1001 | goto synched; | 954 | goto synched; |
| 1002 | 955 | ||
| 1003 | /* Was last pre-synch packet added to input queue ? */ | 956 | /* Was last pre-synch packet added to input queue ? */ |
| 1004 | if (less_eq(pl->next_in_no, l->synch_point)) | 957 | if (less_eq(pl->rcv_nxt, l->synch_point)) |
| 1005 | return false; | 958 | return false; |
| 1006 | 959 | ||
| 1007 | /* Is it still in the input queue ? */ | 960 | /* Is it still in the input queue ? */ |
| 1008 | post_synch = mod(pl->next_in_no - l->synch_point) - 1; | 961 | post_synch = mod(pl->rcv_nxt - l->synch_point) - 1; |
| 1009 | if (skb_queue_len(&pl->inputq) > post_synch) | 962 | if (skb_queue_len(&pl->inputq) > post_synch) |
| 1010 | return false; | 963 | return false; |
| 1011 | synched: | 964 | synched: |
| @@ -1016,13 +969,13 @@ synched: | |||
| 1016 | static void link_retrieve_defq(struct tipc_link *link, | 969 | static void link_retrieve_defq(struct tipc_link *link, |
| 1017 | struct sk_buff_head *list) | 970 | struct sk_buff_head *list) |
| 1018 | { | 971 | { |
| 1019 | u32 seq_no; | 972 | u16 seq_no; |
| 1020 | 973 | ||
| 1021 | if (skb_queue_empty(&link->deferdq)) | 974 | if (skb_queue_empty(&link->deferdq)) |
| 1022 | return; | 975 | return; |
| 1023 | 976 | ||
| 1024 | seq_no = buf_seqno(skb_peek(&link->deferdq)); | 977 | seq_no = buf_seqno(skb_peek(&link->deferdq)); |
| 1025 | if (seq_no == mod(link->next_in_no)) | 978 | if (seq_no == link->rcv_nxt) |
| 1026 | skb_queue_splice_tail_init(&link->deferdq, list); | 979 | skb_queue_splice_tail_init(&link->deferdq, list); |
| 1027 | } | 980 | } |
| 1028 | 981 | ||
| @@ -1043,8 +996,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
| 1043 | struct tipc_link *l_ptr; | 996 | struct tipc_link *l_ptr; |
| 1044 | struct sk_buff *skb1, *tmp; | 997 | struct sk_buff *skb1, *tmp; |
| 1045 | struct tipc_msg *msg; | 998 | struct tipc_msg *msg; |
| 1046 | u32 seq_no; | 999 | u16 seq_no; |
| 1047 | u32 ackd; | 1000 | u16 ackd; |
| 1048 | u32 released; | 1001 | u32 released; |
| 1049 | 1002 | ||
| 1050 | skb2list(skb, &head); | 1003 | skb2list(skb, &head); |
| @@ -1137,18 +1090,20 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
| 1137 | } | 1090 | } |
| 1138 | 1091 | ||
| 1139 | /* Link is now in state WORKING_WORKING */ | 1092 | /* Link is now in state WORKING_WORKING */ |
| 1140 | if (unlikely(seq_no != mod(l_ptr->next_in_no))) { | 1093 | if (unlikely(seq_no != l_ptr->rcv_nxt)) { |
| 1141 | link_handle_out_of_seq_msg(l_ptr, skb); | 1094 | link_handle_out_of_seq_msg(l_ptr, skb); |
| 1142 | link_retrieve_defq(l_ptr, &head); | 1095 | link_retrieve_defq(l_ptr, &head); |
| 1143 | skb = NULL; | 1096 | skb = NULL; |
| 1144 | goto unlock; | 1097 | goto unlock; |
| 1145 | } | 1098 | } |
| 1099 | l_ptr->silent_intv_cnt = 0; | ||
| 1100 | |||
| 1146 | /* Synchronize with parallel link if applicable */ | 1101 | /* Synchronize with parallel link if applicable */ |
| 1147 | if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { | 1102 | if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { |
| 1148 | if (!link_synch(l_ptr)) | 1103 | if (!link_synch(l_ptr)) |
| 1149 | goto unlock; | 1104 | goto unlock; |
| 1150 | } | 1105 | } |
| 1151 | l_ptr->next_in_no++; | 1106 | l_ptr->rcv_nxt++; |
| 1152 | if (unlikely(!skb_queue_empty(&l_ptr->deferdq))) | 1107 | if (unlikely(!skb_queue_empty(&l_ptr->deferdq))) |
| 1153 | link_retrieve_defq(l_ptr, &head); | 1108 | link_retrieve_defq(l_ptr, &head); |
| 1154 | if (unlikely(++l_ptr->rcv_unacked >= TIPC_MIN_LINK_WIN)) { | 1109 | if (unlikely(++l_ptr->rcv_unacked >= TIPC_MIN_LINK_WIN)) { |
| @@ -1268,7 +1223,7 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb) | |||
| 1268 | u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) | 1223 | u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) |
| 1269 | { | 1224 | { |
| 1270 | struct sk_buff *skb1; | 1225 | struct sk_buff *skb1; |
| 1271 | u32 seq_no = buf_seqno(skb); | 1226 | u16 seq_no = buf_seqno(skb); |
| 1272 | 1227 | ||
| 1273 | /* Empty queue ? */ | 1228 | /* Empty queue ? */ |
| 1274 | if (skb_queue_empty(list)) { | 1229 | if (skb_queue_empty(list)) { |
| @@ -1284,7 +1239,7 @@ u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) | |||
| 1284 | 1239 | ||
| 1285 | /* Locate insertion point in queue, then insert; discard if duplicate */ | 1240 | /* Locate insertion point in queue, then insert; discard if duplicate */ |
| 1286 | skb_queue_walk(list, skb1) { | 1241 | skb_queue_walk(list, skb1) { |
| 1287 | u32 curr_seqno = buf_seqno(skb1); | 1242 | u16 curr_seqno = buf_seqno(skb1); |
| 1288 | 1243 | ||
| 1289 | if (seq_no == curr_seqno) { | 1244 | if (seq_no == curr_seqno) { |
| 1290 | kfree_skb(skb); | 1245 | kfree_skb(skb); |
| @@ -1312,14 +1267,14 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
| 1312 | return; | 1267 | return; |
| 1313 | } | 1268 | } |
| 1314 | 1269 | ||
| 1315 | /* Record OOS packet arrival (force mismatch on next timeout) */ | 1270 | /* Record OOS packet arrival */ |
| 1316 | l_ptr->checkpoint--; | 1271 | l_ptr->silent_intv_cnt = 0; |
| 1317 | 1272 | ||
| 1318 | /* | 1273 | /* |
| 1319 | * Discard packet if a duplicate; otherwise add it to deferred queue | 1274 | * Discard packet if a duplicate; otherwise add it to deferred queue |
| 1320 | * and notify peer of gap as per protocol specification | 1275 | * and notify peer of gap as per protocol specification |
| 1321 | */ | 1276 | */ |
| 1322 | if (less(seq_no, mod(l_ptr->next_in_no))) { | 1277 | if (less(seq_no, l_ptr->rcv_nxt)) { |
| 1323 | l_ptr->stats.duplicates++; | 1278 | l_ptr->stats.duplicates++; |
| 1324 | kfree_skb(buf); | 1279 | kfree_skb(buf); |
| 1325 | return; | 1280 | return; |
| @@ -1344,6 +1299,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1344 | struct tipc_msg *msg = l_ptr->pmsg; | 1299 | struct tipc_msg *msg = l_ptr->pmsg; |
| 1345 | u32 msg_size = sizeof(l_ptr->proto_msg); | 1300 | u32 msg_size = sizeof(l_ptr->proto_msg); |
| 1346 | int r_flag; | 1301 | int r_flag; |
| 1302 | u16 last_rcv; | ||
| 1347 | 1303 | ||
| 1348 | /* Don't send protocol message during link failover */ | 1304 | /* Don't send protocol message during link failover */ |
| 1349 | if (l_ptr->flags & LINK_FAILINGOVER) | 1305 | if (l_ptr->flags & LINK_FAILINGOVER) |
| @@ -1360,16 +1316,14 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1360 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net)); | 1316 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net)); |
| 1361 | 1317 | ||
| 1362 | if (msg_typ == STATE_MSG) { | 1318 | if (msg_typ == STATE_MSG) { |
| 1363 | u32 next_sent = mod(l_ptr->next_out_no); | 1319 | u16 next_sent = l_ptr->snd_nxt; |
| 1364 | 1320 | ||
| 1365 | if (!tipc_link_is_up(l_ptr)) | 1321 | if (!tipc_link_is_up(l_ptr)) |
| 1366 | return; | 1322 | return; |
| 1367 | if (skb_queue_len(&l_ptr->backlogq)) | ||
| 1368 | next_sent = buf_seqno(skb_peek(&l_ptr->backlogq)); | ||
| 1369 | msg_set_next_sent(msg, next_sent); | 1323 | msg_set_next_sent(msg, next_sent); |
| 1370 | if (!skb_queue_empty(&l_ptr->deferdq)) { | 1324 | if (!skb_queue_empty(&l_ptr->deferdq)) { |
| 1371 | u32 rec = buf_seqno(skb_peek(&l_ptr->deferdq)); | 1325 | last_rcv = buf_seqno(skb_peek(&l_ptr->deferdq)); |
| 1372 | gap = mod(rec - mod(l_ptr->next_in_no)); | 1326 | gap = mod(last_rcv - l_ptr->rcv_nxt); |
| 1373 | } | 1327 | } |
| 1374 | msg_set_seq_gap(msg, gap); | 1328 | msg_set_seq_gap(msg, gap); |
| 1375 | if (gap) | 1329 | if (gap) |
| @@ -1377,7 +1331,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1377 | msg_set_link_tolerance(msg, tolerance); | 1331 | msg_set_link_tolerance(msg, tolerance); |
| 1378 | msg_set_linkprio(msg, priority); | 1332 | msg_set_linkprio(msg, priority); |
| 1379 | msg_set_max_pkt(msg, l_ptr->mtu); | 1333 | msg_set_max_pkt(msg, l_ptr->mtu); |
| 1380 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1334 | msg_set_ack(msg, mod(l_ptr->rcv_nxt - 1)); |
| 1381 | msg_set_probe(msg, probe_msg != 0); | 1335 | msg_set_probe(msg, probe_msg != 0); |
| 1382 | if (probe_msg) | 1336 | if (probe_msg) |
| 1383 | l_ptr->stats.sent_probes++; | 1337 | l_ptr->stats.sent_probes++; |
| @@ -1397,7 +1351,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1397 | msg_set_linkprio(msg, l_ptr->priority); | 1351 | msg_set_linkprio(msg, l_ptr->priority); |
| 1398 | msg_set_size(msg, msg_size); | 1352 | msg_set_size(msg, msg_size); |
| 1399 | 1353 | ||
| 1400 | msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); | 1354 | msg_set_seqno(msg, mod(l_ptr->snd_nxt + (0xffff / 2))); |
| 1401 | 1355 | ||
| 1402 | buf = tipc_buf_acquire(msg_size); | 1356 | buf = tipc_buf_acquire(msg_size); |
| 1403 | if (!buf) | 1357 | if (!buf) |
| @@ -1496,17 +1450,15 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, | |||
| 1496 | } | 1450 | } |
| 1497 | 1451 | ||
| 1498 | /* Record reception; force mismatch at next timeout: */ | 1452 | /* Record reception; force mismatch at next timeout: */ |
| 1499 | l_ptr->checkpoint--; | 1453 | l_ptr->silent_intv_cnt = 0; |
| 1500 | 1454 | ||
| 1501 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | 1455 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); |
| 1502 | l_ptr->stats.recv_states++; | 1456 | l_ptr->stats.recv_states++; |
| 1503 | if (link_reset_unknown(l_ptr)) | 1457 | if (link_reset_unknown(l_ptr)) |
| 1504 | break; | 1458 | break; |
| 1505 | 1459 | ||
| 1506 | if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { | 1460 | if (less_eq(l_ptr->rcv_nxt, msg_next_sent(msg))) |
| 1507 | rec_gap = mod(msg_next_sent(msg) - | 1461 | rec_gap = mod(msg_next_sent(msg) - l_ptr->rcv_nxt); |
| 1508 | mod(l_ptr->next_in_no)); | ||
| 1509 | } | ||
| 1510 | 1462 | ||
| 1511 | if (msg_probe(msg)) | 1463 | if (msg_probe(msg)) |
| 1512 | l_ptr->stats.recv_probes++; | 1464 | l_ptr->stats.recv_probes++; |
| @@ -1580,6 +1532,11 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr) | |||
| 1580 | 1532 | ||
| 1581 | tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, TUNNEL_PROTOCOL, | 1533 | tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, TUNNEL_PROTOCOL, |
| 1582 | FAILOVER_MSG, INT_H_SIZE, l_ptr->addr); | 1534 | FAILOVER_MSG, INT_H_SIZE, l_ptr->addr); |
| 1535 | |||
| 1536 | skb_queue_walk(&l_ptr->backlogq, skb) { | ||
| 1537 | msg_set_seqno(buf_msg(skb), l_ptr->snd_nxt); | ||
| 1538 | l_ptr->snd_nxt = mod(l_ptr->snd_nxt + 1); | ||
| 1539 | } | ||
| 1583 | skb_queue_splice_tail_init(&l_ptr->backlogq, &l_ptr->transmq); | 1540 | skb_queue_splice_tail_init(&l_ptr->backlogq, &l_ptr->transmq); |
| 1584 | tipc_link_purge_backlog(l_ptr); | 1541 | tipc_link_purge_backlog(l_ptr); |
| 1585 | msgcount = skb_queue_len(&l_ptr->transmq); | 1542 | msgcount = skb_queue_len(&l_ptr->transmq); |
| @@ -1640,6 +1597,7 @@ void tipc_link_dup_queue_xmit(struct tipc_link *link, | |||
| 1640 | struct tipc_msg tnl_hdr; | 1597 | struct tipc_msg tnl_hdr; |
| 1641 | struct sk_buff_head *queue = &link->transmq; | 1598 | struct sk_buff_head *queue = &link->transmq; |
| 1642 | int mcnt; | 1599 | int mcnt; |
| 1600 | u16 seqno; | ||
| 1643 | 1601 | ||
| 1644 | tipc_msg_init(link_own_addr(link), &tnl_hdr, TUNNEL_PROTOCOL, | 1602 | tipc_msg_init(link_own_addr(link), &tnl_hdr, TUNNEL_PROTOCOL, |
| 1645 | SYNCH_MSG, INT_H_SIZE, link->addr); | 1603 | SYNCH_MSG, INT_H_SIZE, link->addr); |
| @@ -1653,7 +1611,7 @@ tunnel_queue: | |||
| 1653 | struct tipc_msg *msg = buf_msg(skb); | 1611 | struct tipc_msg *msg = buf_msg(skb); |
| 1654 | u32 len = msg_size(msg); | 1612 | u32 len = msg_size(msg); |
| 1655 | 1613 | ||
| 1656 | msg_set_ack(msg, mod(link->next_in_no - 1)); | 1614 | msg_set_ack(msg, mod(link->rcv_nxt - 1)); |
| 1657 | msg_set_bcast_ack(msg, link->owner->bclink.last_in); | 1615 | msg_set_bcast_ack(msg, link->owner->bclink.last_in); |
| 1658 | msg_set_size(&tnl_hdr, len + INT_H_SIZE); | 1616 | msg_set_size(&tnl_hdr, len + INT_H_SIZE); |
| 1659 | outskb = tipc_buf_acquire(len + INT_H_SIZE); | 1617 | outskb = tipc_buf_acquire(len + INT_H_SIZE); |
| @@ -1671,6 +1629,11 @@ tunnel_queue: | |||
| 1671 | } | 1629 | } |
| 1672 | if (queue == &link->backlogq) | 1630 | if (queue == &link->backlogq) |
| 1673 | return; | 1631 | return; |
| 1632 | seqno = link->snd_nxt; | ||
| 1633 | skb_queue_walk(&link->backlogq, skb) { | ||
| 1634 | msg_set_seqno(buf_msg(skb), seqno); | ||
| 1635 | seqno = mod(seqno + 1); | ||
| 1636 | } | ||
| 1674 | queue = &link->backlogq; | 1637 | queue = &link->backlogq; |
| 1675 | goto tunnel_queue; | 1638 | goto tunnel_queue; |
| 1676 | } | 1639 | } |
| @@ -1742,8 +1705,8 @@ static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol) | |||
| 1742 | return; | 1705 | return; |
| 1743 | 1706 | ||
| 1744 | l_ptr->tolerance = tol; | 1707 | l_ptr->tolerance = tol; |
| 1745 | l_ptr->cont_intv = msecs_to_jiffies(intv); | 1708 | l_ptr->keepalive_intv = msecs_to_jiffies(intv); |
| 1746 | l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->cont_intv) / 4); | 1709 | l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->keepalive_intv)); |
| 1747 | } | 1710 | } |
| 1748 | 1711 | ||
| 1749 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) | 1712 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) |
| @@ -1803,8 +1766,8 @@ static struct tipc_node *tipc_link_find_owner(struct net *net, | |||
| 1803 | static void link_reset_statistics(struct tipc_link *l_ptr) | 1766 | static void link_reset_statistics(struct tipc_link *l_ptr) |
| 1804 | { | 1767 | { |
| 1805 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); | 1768 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); |
| 1806 | l_ptr->stats.sent_info = l_ptr->next_out_no; | 1769 | l_ptr->stats.sent_info = l_ptr->snd_nxt; |
| 1807 | l_ptr->stats.recv_info = l_ptr->next_in_no; | 1770 | l_ptr->stats.recv_info = l_ptr->rcv_nxt; |
| 1808 | } | 1771 | } |
| 1809 | 1772 | ||
| 1810 | static void link_print(struct tipc_link *l_ptr, const char *str) | 1773 | static void link_print(struct tipc_link *l_ptr, const char *str) |
| @@ -1893,6 +1856,9 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) | |||
| 1893 | 1856 | ||
| 1894 | name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | 1857 | name = nla_data(attrs[TIPC_NLA_LINK_NAME]); |
| 1895 | 1858 | ||
| 1859 | if (strcmp(name, tipc_bclink_name) == 0) | ||
| 1860 | return tipc_nl_bc_link_set(net, attrs); | ||
| 1861 | |||
| 1896 | node = tipc_link_find_owner(net, name, &bearer_id); | 1862 | node = tipc_link_find_owner(net, name, &bearer_id); |
| 1897 | if (!node) | 1863 | if (!node) |
| 1898 | return -EINVAL; | 1864 | return -EINVAL; |
| @@ -2034,9 +2000,9 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | |||
| 2034 | goto attr_msg_full; | 2000 | goto attr_msg_full; |
| 2035 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu)) | 2001 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu)) |
| 2036 | goto attr_msg_full; | 2002 | goto attr_msg_full; |
| 2037 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->next_in_no)) | 2003 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->rcv_nxt)) |
| 2038 | goto attr_msg_full; | 2004 | goto attr_msg_full; |
| 2039 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->next_out_no)) | 2005 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->snd_nxt)) |
| 2040 | goto attr_msg_full; | 2006 | goto attr_msg_full; |
| 2041 | 2007 | ||
| 2042 | if (tipc_link_is_up(link)) | 2008 | if (tipc_link_is_up(link)) |
| @@ -2175,50 +2141,53 @@ out: | |||
| 2175 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) | 2141 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) |
| 2176 | { | 2142 | { |
| 2177 | struct net *net = genl_info_net(info); | 2143 | struct net *net = genl_info_net(info); |
| 2178 | struct sk_buff *ans_skb; | ||
| 2179 | struct tipc_nl_msg msg; | 2144 | struct tipc_nl_msg msg; |
| 2180 | struct tipc_link *link; | ||
| 2181 | struct tipc_node *node; | ||
| 2182 | char *name; | 2145 | char *name; |
| 2183 | int bearer_id; | ||
| 2184 | int err; | 2146 | int err; |
| 2185 | 2147 | ||
| 2148 | msg.portid = info->snd_portid; | ||
| 2149 | msg.seq = info->snd_seq; | ||
| 2150 | |||
| 2186 | if (!info->attrs[TIPC_NLA_LINK_NAME]) | 2151 | if (!info->attrs[TIPC_NLA_LINK_NAME]) |
| 2187 | return -EINVAL; | 2152 | return -EINVAL; |
| 2188 | |||
| 2189 | name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); | 2153 | name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); |
| 2190 | node = tipc_link_find_owner(net, name, &bearer_id); | ||
| 2191 | if (!node) | ||
| 2192 | return -EINVAL; | ||
| 2193 | 2154 | ||
| 2194 | ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 2155 | msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
| 2195 | if (!ans_skb) | 2156 | if (!msg.skb) |
| 2196 | return -ENOMEM; | 2157 | return -ENOMEM; |
| 2197 | 2158 | ||
| 2198 | msg.skb = ans_skb; | 2159 | if (strcmp(name, tipc_bclink_name) == 0) { |
| 2199 | msg.portid = info->snd_portid; | 2160 | err = tipc_nl_add_bc_link(net, &msg); |
| 2200 | msg.seq = info->snd_seq; | 2161 | if (err) { |
| 2201 | 2162 | nlmsg_free(msg.skb); | |
| 2202 | tipc_node_lock(node); | 2163 | return err; |
| 2203 | link = node->links[bearer_id]; | 2164 | } |
| 2204 | if (!link) { | 2165 | } else { |
| 2205 | err = -EINVAL; | 2166 | int bearer_id; |
| 2206 | goto err_out; | 2167 | struct tipc_node *node; |
| 2207 | } | 2168 | struct tipc_link *link; |
| 2208 | |||
| 2209 | err = __tipc_nl_add_link(net, &msg, link, 0); | ||
| 2210 | if (err) | ||
| 2211 | goto err_out; | ||
| 2212 | 2169 | ||
| 2213 | tipc_node_unlock(node); | 2170 | node = tipc_link_find_owner(net, name, &bearer_id); |
| 2171 | if (!node) | ||
| 2172 | return -EINVAL; | ||
| 2214 | 2173 | ||
| 2215 | return genlmsg_reply(ans_skb, info); | 2174 | tipc_node_lock(node); |
| 2175 | link = node->links[bearer_id]; | ||
| 2176 | if (!link) { | ||
| 2177 | tipc_node_unlock(node); | ||
| 2178 | nlmsg_free(msg.skb); | ||
| 2179 | return -EINVAL; | ||
| 2180 | } | ||
| 2216 | 2181 | ||
| 2217 | err_out: | 2182 | err = __tipc_nl_add_link(net, &msg, link, 0); |
| 2218 | tipc_node_unlock(node); | 2183 | tipc_node_unlock(node); |
| 2219 | nlmsg_free(ans_skb); | 2184 | if (err) { |
| 2185 | nlmsg_free(msg.skb); | ||
| 2186 | return err; | ||
| 2187 | } | ||
| 2188 | } | ||
| 2220 | 2189 | ||
| 2221 | return err; | 2190 | return genlmsg_reply(msg.skb, info); |
| 2222 | } | 2191 | } |
| 2223 | 2192 | ||
| 2224 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) | 2193 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) |
diff --git a/net/tipc/link.h b/net/tipc/link.h index b5b4e3554d4e..ae0a0ea572f2 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
| @@ -107,30 +107,29 @@ struct tipc_stats { | |||
| 107 | * @owner: pointer to peer node | 107 | * @owner: pointer to peer node |
| 108 | * @refcnt: reference counter for permanent references (owner node & timer) | 108 | * @refcnt: reference counter for permanent references (owner node & timer) |
| 109 | * @flags: execution state flags for link endpoint instance | 109 | * @flags: execution state flags for link endpoint instance |
| 110 | * @checkpoint: reference point for triggering link continuity checking | ||
| 111 | * @peer_session: link session # being used by peer end of link | 110 | * @peer_session: link session # being used by peer end of link |
| 112 | * @peer_bearer_id: bearer id used by link's peer endpoint | 111 | * @peer_bearer_id: bearer id used by link's peer endpoint |
| 113 | * @bearer_id: local bearer id used by link | 112 | * @bearer_id: local bearer id used by link |
| 114 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | 113 | * @tolerance: minimum link continuity loss needed to reset link [in ms] |
| 115 | * @cont_intv: link continuity testing interval | 114 | * @keepalive_intv: link keepalive timer interval |
| 116 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | 115 | * @abort_limit: # of unacknowledged continuity probes needed to reset link |
| 117 | * @state: current state of link FSM | 116 | * @state: current state of link FSM |
| 118 | * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state | 117 | * @silent_intv_cnt: # of timer intervals without any reception from peer |
| 119 | * @proto_msg: template for control messages generated by link | 118 | * @proto_msg: template for control messages generated by link |
| 120 | * @pmsg: convenience pointer to "proto_msg" field | 119 | * @pmsg: convenience pointer to "proto_msg" field |
| 121 | * @priority: current link priority | 120 | * @priority: current link priority |
| 122 | * @net_plane: current link network plane ('A' through 'H') | 121 | * @net_plane: current link network plane ('A' through 'H') |
| 123 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) | 122 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) |
| 124 | * @exp_msg_count: # of tunnelled messages expected during link changeover | 123 | * @exp_msg_count: # of tunnelled messages expected during link changeover |
| 125 | * @reset_checkpoint: seq # of last acknowledged message at time of link reset | 124 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset |
| 126 | * @mtu: current maximum packet size for this link | 125 | * @mtu: current maximum packet size for this link |
| 127 | * @advertised_mtu: advertised own mtu when link is being established | 126 | * @advertised_mtu: advertised own mtu when link is being established |
| 128 | * @transmitq: queue for sent, non-acked messages | 127 | * @transmitq: queue for sent, non-acked messages |
| 129 | * @backlogq: queue for messages waiting to be sent | 128 | * @backlogq: queue for messages waiting to be sent |
| 130 | * @next_out_no: next sequence number to use for outbound messages | 129 | * @snt_nxt: next sequence number to use for outbound messages |
| 131 | * @last_retransmitted: sequence number of most recently retransmitted message | 130 | * @last_retransmitted: sequence number of most recently retransmitted message |
| 132 | * @stale_count: # of identical retransmit requests made by peer | 131 | * @stale_count: # of identical retransmit requests made by peer |
| 133 | * @next_in_no: next sequence number to expect for inbound messages | 132 | * @rcv_nxt: next sequence number to expect for inbound messages |
| 134 | * @deferred_queue: deferred queue saved OOS b'cast message received from node | 133 | * @deferred_queue: deferred queue saved OOS b'cast message received from node |
| 135 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer | 134 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer |
| 136 | * @inputq: buffer queue for messages to be delivered upwards | 135 | * @inputq: buffer queue for messages to be delivered upwards |
| @@ -151,15 +150,14 @@ struct tipc_link { | |||
| 151 | 150 | ||
| 152 | /* Management and link supervision data */ | 151 | /* Management and link supervision data */ |
| 153 | unsigned int flags; | 152 | unsigned int flags; |
| 154 | u32 checkpoint; | ||
| 155 | u32 peer_session; | 153 | u32 peer_session; |
| 156 | u32 peer_bearer_id; | 154 | u32 peer_bearer_id; |
| 157 | u32 bearer_id; | 155 | u32 bearer_id; |
| 158 | u32 tolerance; | 156 | u32 tolerance; |
| 159 | unsigned long cont_intv; | 157 | unsigned long keepalive_intv; |
| 160 | u32 abort_limit; | 158 | u32 abort_limit; |
| 161 | int state; | 159 | int state; |
| 162 | u32 fsm_msg_cnt; | 160 | u32 silent_intv_cnt; |
| 163 | struct { | 161 | struct { |
| 164 | unchar hdr[INT_H_SIZE]; | 162 | unchar hdr[INT_H_SIZE]; |
| 165 | unchar body[TIPC_MAX_IF_NAME]; | 163 | unchar body[TIPC_MAX_IF_NAME]; |
| @@ -185,13 +183,13 @@ struct tipc_link { | |||
| 185 | u16 len; | 183 | u16 len; |
| 186 | u16 limit; | 184 | u16 limit; |
| 187 | } backlog[5]; | 185 | } backlog[5]; |
| 188 | u32 next_out_no; | 186 | u16 snd_nxt; |
| 187 | u16 last_retransm; | ||
| 189 | u32 window; | 188 | u32 window; |
| 190 | u32 last_retransmitted; | ||
| 191 | u32 stale_count; | 189 | u32 stale_count; |
| 192 | 190 | ||
| 193 | /* Reception */ | 191 | /* Reception */ |
| 194 | u32 next_in_no; | 192 | u16 rcv_nxt; |
| 195 | u32 rcv_unacked; | 193 | u32 rcv_unacked; |
| 196 | struct sk_buff_head deferdq; | 194 | struct sk_buff_head deferdq; |
| 197 | struct sk_buff_head inputq; | 195 | struct sk_buff_head inputq; |
| @@ -213,17 +211,16 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 213 | struct tipc_bearer *b_ptr, | 211 | struct tipc_bearer *b_ptr, |
| 214 | const struct tipc_media_addr *media_addr); | 212 | const struct tipc_media_addr *media_addr); |
| 215 | void tipc_link_delete(struct tipc_link *link); | 213 | void tipc_link_delete(struct tipc_link *link); |
| 216 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id, | 214 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id); |
| 217 | bool shutting_down); | ||
| 218 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr); | 215 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr); |
| 219 | void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest); | 216 | void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest); |
| 220 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); | 217 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); |
| 221 | int tipc_link_is_up(struct tipc_link *l_ptr); | 218 | int tipc_link_is_up(struct tipc_link *l_ptr); |
| 222 | int tipc_link_is_active(struct tipc_link *l_ptr); | 219 | int tipc_link_is_active(struct tipc_link *l_ptr); |
| 223 | void tipc_link_purge_queues(struct tipc_link *l_ptr); | 220 | void tipc_link_purge_queues(struct tipc_link *l_ptr); |
| 221 | void tipc_link_purge_backlog(struct tipc_link *l); | ||
| 224 | void tipc_link_reset_all(struct tipc_node *node); | 222 | void tipc_link_reset_all(struct tipc_node *node); |
| 225 | void tipc_link_reset(struct tipc_link *l_ptr); | 223 | void tipc_link_reset(struct tipc_link *l_ptr); |
| 226 | void tipc_link_reset_list(struct net *net, unsigned int bearer_id); | ||
| 227 | int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, | 224 | int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, |
| 228 | u32 selector); | 225 | u32 selector); |
| 229 | int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest, | 226 | int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest, |
| @@ -247,39 +244,6 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info); | |||
| 247 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); | 244 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); |
| 248 | void link_prepare_wakeup(struct tipc_link *l); | 245 | void link_prepare_wakeup(struct tipc_link *l); |
| 249 | 246 | ||
| 250 | /* | ||
| 251 | * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) | ||
| 252 | */ | ||
| 253 | static inline u32 buf_seqno(struct sk_buff *buf) | ||
| 254 | { | ||
| 255 | return msg_seqno(buf_msg(buf)); | ||
| 256 | } | ||
| 257 | |||
| 258 | static inline u32 mod(u32 x) | ||
| 259 | { | ||
| 260 | return x & 0xffffu; | ||
| 261 | } | ||
| 262 | |||
| 263 | static inline int less_eq(u32 left, u32 right) | ||
| 264 | { | ||
| 265 | return mod(right - left) < 32768u; | ||
| 266 | } | ||
| 267 | |||
| 268 | static inline int more(u32 left, u32 right) | ||
| 269 | { | ||
| 270 | return !less_eq(left, right); | ||
| 271 | } | ||
| 272 | |||
| 273 | static inline int less(u32 left, u32 right) | ||
| 274 | { | ||
| 275 | return less_eq(left, right) && (mod(right) != mod(left)); | ||
| 276 | } | ||
| 277 | |||
| 278 | static inline u32 lesser(u32 left, u32 right) | ||
| 279 | { | ||
| 280 | return less_eq(left, right) ? left : right; | ||
| 281 | } | ||
| 282 | |||
| 283 | static inline u32 link_own_addr(struct tipc_link *l) | 247 | static inline u32 link_own_addr(struct tipc_link *l) |
| 284 | { | 248 | { |
| 285 | return msg_prevnode(l->pmsg); | 249 | return msg_prevnode(l->pmsg); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index c3e96e815418..08b4cc7d496d 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
| @@ -331,16 +331,15 @@ error: | |||
| 331 | 331 | ||
| 332 | /** | 332 | /** |
| 333 | * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one | 333 | * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one |
| 334 | * @bskb: the buffer to append to ("bundle") | 334 | * @skb: the buffer to append to ("bundle") |
| 335 | * @skb: buffer to be appended | 335 | * @msg: message to be appended |
| 336 | * @mtu: max allowable size for the bundle buffer | 336 | * @mtu: max allowable size for the bundle buffer |
| 337 | * Consumes buffer if successful | 337 | * Consumes buffer if successful |
| 338 | * Returns true if bundling could be performed, otherwise false | 338 | * Returns true if bundling could be performed, otherwise false |
| 339 | */ | 339 | */ |
| 340 | bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu) | 340 | bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu) |
| 341 | { | 341 | { |
| 342 | struct tipc_msg *bmsg; | 342 | struct tipc_msg *bmsg; |
| 343 | struct tipc_msg *msg = buf_msg(skb); | ||
| 344 | unsigned int bsz; | 343 | unsigned int bsz; |
| 345 | unsigned int msz = msg_size(msg); | 344 | unsigned int msz = msg_size(msg); |
| 346 | u32 start, pad; | 345 | u32 start, pad; |
| @@ -348,9 +347,9 @@ bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu) | |||
| 348 | 347 | ||
| 349 | if (likely(msg_user(msg) == MSG_FRAGMENTER)) | 348 | if (likely(msg_user(msg) == MSG_FRAGMENTER)) |
| 350 | return false; | 349 | return false; |
| 351 | if (!bskb) | 350 | if (!skb) |
| 352 | return false; | 351 | return false; |
| 353 | bmsg = buf_msg(bskb); | 352 | bmsg = buf_msg(skb); |
| 354 | bsz = msg_size(bmsg); | 353 | bsz = msg_size(bmsg); |
| 355 | start = align(bsz); | 354 | start = align(bsz); |
| 356 | pad = start - bsz; | 355 | pad = start - bsz; |
| @@ -359,18 +358,20 @@ bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu) | |||
| 359 | return false; | 358 | return false; |
| 360 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) | 359 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) |
| 361 | return false; | 360 | return false; |
| 362 | if (likely(msg_user(bmsg) != MSG_BUNDLER)) | 361 | if (unlikely(msg_user(bmsg) != MSG_BUNDLER)) |
| 363 | return false; | 362 | return false; |
| 364 | if (unlikely(skb_tailroom(bskb) < (pad + msz))) | 363 | if (unlikely(skb_tailroom(skb) < (pad + msz))) |
| 365 | return false; | 364 | return false; |
| 366 | if (unlikely(max < (start + msz))) | 365 | if (unlikely(max < (start + msz))) |
| 367 | return false; | 366 | return false; |
| 367 | if ((msg_importance(msg) < TIPC_SYSTEM_IMPORTANCE) && | ||
| 368 | (msg_importance(bmsg) == TIPC_SYSTEM_IMPORTANCE)) | ||
| 369 | return false; | ||
| 368 | 370 | ||
| 369 | skb_put(bskb, pad + msz); | 371 | skb_put(skb, pad + msz); |
| 370 | skb_copy_to_linear_data_offset(bskb, start, skb->data, msz); | 372 | skb_copy_to_linear_data_offset(skb, start, msg, msz); |
| 371 | msg_set_size(bmsg, start + msz); | 373 | msg_set_size(bmsg, start + msz); |
| 372 | msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1); | 374 | msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1); |
| 373 | kfree_skb(skb); | ||
| 374 | return true; | 375 | return true; |
| 375 | } | 376 | } |
| 376 | 377 | ||
| @@ -416,18 +417,18 @@ none: | |||
| 416 | 417 | ||
| 417 | /** | 418 | /** |
| 418 | * tipc_msg_make_bundle(): Create bundle buf and append message to its tail | 419 | * tipc_msg_make_bundle(): Create bundle buf and append message to its tail |
| 419 | * @list: the buffer chain | 420 | * @list: the buffer chain, where head is the buffer to replace/append |
| 420 | * @skb: buffer to be appended and replaced | 421 | * @skb: buffer to be created, appended to and returned in case of success |
| 422 | * @msg: message to be appended | ||
| 421 | * @mtu: max allowable size for the bundle buffer, inclusive header | 423 | * @mtu: max allowable size for the bundle buffer, inclusive header |
| 422 | * @dnode: destination node for message. (Not always present in header) | 424 | * @dnode: destination node for message. (Not always present in header) |
| 423 | * Replaces buffer if successful | ||
| 424 | * Returns true if success, otherwise false | 425 | * Returns true if success, otherwise false |
| 425 | */ | 426 | */ |
| 426 | bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode) | 427 | bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, |
| 428 | u32 mtu, u32 dnode) | ||
| 427 | { | 429 | { |
| 428 | struct sk_buff *bskb; | 430 | struct sk_buff *_skb; |
| 429 | struct tipc_msg *bmsg; | 431 | struct tipc_msg *bmsg; |
| 430 | struct tipc_msg *msg = buf_msg(*skb); | ||
| 431 | u32 msz = msg_size(msg); | 432 | u32 msz = msg_size(msg); |
| 432 | u32 max = mtu - INT_H_SIZE; | 433 | u32 max = mtu - INT_H_SIZE; |
| 433 | 434 | ||
| @@ -440,19 +441,23 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode) | |||
| 440 | if (msz > (max / 2)) | 441 | if (msz > (max / 2)) |
| 441 | return false; | 442 | return false; |
| 442 | 443 | ||
| 443 | bskb = tipc_buf_acquire(max); | 444 | _skb = tipc_buf_acquire(max); |
| 444 | if (!bskb) | 445 | if (!_skb) |
| 445 | return false; | 446 | return false; |
| 446 | 447 | ||
| 447 | skb_trim(bskb, INT_H_SIZE); | 448 | skb_trim(_skb, INT_H_SIZE); |
| 448 | bmsg = buf_msg(bskb); | 449 | bmsg = buf_msg(_skb); |
| 449 | tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0, | 450 | tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0, |
| 450 | INT_H_SIZE, dnode); | 451 | INT_H_SIZE, dnode); |
| 452 | if (msg_isdata(msg)) | ||
| 453 | msg_set_importance(bmsg, TIPC_CRITICAL_IMPORTANCE); | ||
| 454 | else | ||
| 455 | msg_set_importance(bmsg, TIPC_SYSTEM_IMPORTANCE); | ||
| 451 | msg_set_seqno(bmsg, msg_seqno(msg)); | 456 | msg_set_seqno(bmsg, msg_seqno(msg)); |
| 452 | msg_set_ack(bmsg, msg_ack(msg)); | 457 | msg_set_ack(bmsg, msg_ack(msg)); |
| 453 | msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); | 458 | msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); |
| 454 | tipc_msg_bundle(bskb, *skb, mtu); | 459 | tipc_msg_bundle(_skb, msg, mtu); |
| 455 | *skb = bskb; | 460 | *skb = _skb; |
| 456 | return true; | 461 | return true; |
| 457 | } | 462 | } |
| 458 | 463 | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index e1d3595e2ee9..19c45fb66238 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
| @@ -313,12 +313,12 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) | |||
| 313 | msg_set_bits(m, 1, 19, 0x3, n); | 313 | msg_set_bits(m, 1, 19, 0x3, n); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static inline u32 msg_bcast_ack(struct tipc_msg *m) | 316 | static inline u16 msg_bcast_ack(struct tipc_msg *m) |
| 317 | { | 317 | { |
| 318 | return msg_bits(m, 1, 0, 0xffff); | 318 | return msg_bits(m, 1, 0, 0xffff); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) | 321 | static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n) |
| 322 | { | 322 | { |
| 323 | msg_set_bits(m, 1, 0, 0xffff, n); | 323 | msg_set_bits(m, 1, 0, 0xffff, n); |
| 324 | } | 324 | } |
| @@ -327,22 +327,22 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) | |||
| 327 | /* | 327 | /* |
| 328 | * Word 2 | 328 | * Word 2 |
| 329 | */ | 329 | */ |
| 330 | static inline u32 msg_ack(struct tipc_msg *m) | 330 | static inline u16 msg_ack(struct tipc_msg *m) |
| 331 | { | 331 | { |
| 332 | return msg_bits(m, 2, 16, 0xffff); | 332 | return msg_bits(m, 2, 16, 0xffff); |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | static inline void msg_set_ack(struct tipc_msg *m, u32 n) | 335 | static inline void msg_set_ack(struct tipc_msg *m, u16 n) |
| 336 | { | 336 | { |
| 337 | msg_set_bits(m, 2, 16, 0xffff, n); | 337 | msg_set_bits(m, 2, 16, 0xffff, n); |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static inline u32 msg_seqno(struct tipc_msg *m) | 340 | static inline u16 msg_seqno(struct tipc_msg *m) |
| 341 | { | 341 | { |
| 342 | return msg_bits(m, 2, 0, 0xffff); | 342 | return msg_bits(m, 2, 0, 0xffff); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | static inline void msg_set_seqno(struct tipc_msg *m, u32 n) | 345 | static inline void msg_set_seqno(struct tipc_msg *m, u16 n) |
| 346 | { | 346 | { |
| 347 | msg_set_bits(m, 2, 0, 0xffff, n); | 347 | msg_set_bits(m, 2, 0, 0xffff, n); |
| 348 | } | 348 | } |
| @@ -352,18 +352,22 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n) | |||
| 352 | */ | 352 | */ |
| 353 | static inline u32 msg_importance(struct tipc_msg *m) | 353 | static inline u32 msg_importance(struct tipc_msg *m) |
| 354 | { | 354 | { |
| 355 | if (unlikely(msg_user(m) == MSG_FRAGMENTER)) | 355 | int usr = msg_user(m); |
| 356 | |||
| 357 | if (likely((usr <= TIPC_CRITICAL_IMPORTANCE) && !msg_errcode(m))) | ||
| 358 | return usr; | ||
| 359 | if ((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER)) | ||
| 356 | return msg_bits(m, 5, 13, 0x7); | 360 | return msg_bits(m, 5, 13, 0x7); |
| 357 | if (likely(msg_isdata(m) && !msg_errcode(m))) | ||
| 358 | return msg_user(m); | ||
| 359 | return TIPC_SYSTEM_IMPORTANCE; | 361 | return TIPC_SYSTEM_IMPORTANCE; |
| 360 | } | 362 | } |
| 361 | 363 | ||
| 362 | static inline void msg_set_importance(struct tipc_msg *m, u32 i) | 364 | static inline void msg_set_importance(struct tipc_msg *m, u32 i) |
| 363 | { | 365 | { |
| 364 | if (unlikely(msg_user(m) == MSG_FRAGMENTER)) | 366 | int usr = msg_user(m); |
| 367 | |||
| 368 | if (likely((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER))) | ||
| 365 | msg_set_bits(m, 5, 13, 0x7, i); | 369 | msg_set_bits(m, 5, 13, 0x7, i); |
| 366 | else if (likely(i < TIPC_SYSTEM_IMPORTANCE)) | 370 | else if (i < TIPC_SYSTEM_IMPORTANCE) |
| 367 | msg_set_user(m, i); | 371 | msg_set_user(m, i); |
| 368 | else | 372 | else |
| 369 | pr_warn("Trying to set illegal importance in message\n"); | 373 | pr_warn("Trying to set illegal importance in message\n"); |
| @@ -772,9 +776,9 @@ struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, | |||
| 772 | uint data_sz, u32 dnode, u32 onode, | 776 | uint data_sz, u32 dnode, u32 onode, |
| 773 | u32 dport, u32 oport, int errcode); | 777 | u32 dport, u32 oport, int errcode); |
| 774 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); | 778 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); |
| 775 | bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu); | 779 | bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu); |
| 776 | 780 | bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, | |
| 777 | bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode); | 781 | u32 mtu, u32 dnode); |
| 778 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); | 782 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); |
| 779 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, | 783 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, |
| 780 | int offset, int dsz, int mtu, struct sk_buff_head *list); | 784 | int offset, int dsz, int mtu, struct sk_buff_head *list); |
| @@ -782,6 +786,11 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode, | |||
| 782 | int *err); | 786 | int *err); |
| 783 | struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); | 787 | struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); |
| 784 | 788 | ||
| 789 | static inline u16 buf_seqno(struct sk_buff *skb) | ||
| 790 | { | ||
| 791 | return msg_seqno(buf_msg(skb)); | ||
| 792 | } | ||
| 793 | |||
| 785 | /* tipc_skb_peek(): peek and reserve first buffer in list | 794 | /* tipc_skb_peek(): peek and reserve first buffer in list |
| 786 | * @list: list to be peeked in | 795 | * @list: list to be peeked in |
| 787 | * Returns pointer to first buffer in list, if any | 796 | * Returns pointer to first buffer in list, if any |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index ab0ac62a1287..0f47f08bf38f 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
| @@ -330,13 +330,9 @@ static struct publication *tipc_nameseq_insert_publ(struct net *net, | |||
| 330 | 330 | ||
| 331 | /* Any subscriptions waiting for notification? */ | 331 | /* Any subscriptions waiting for notification? */ |
| 332 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | 332 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { |
| 333 | tipc_subscr_report_overlap(s, | 333 | tipc_subscrp_report_overlap(s, publ->lower, publ->upper, |
| 334 | publ->lower, | 334 | TIPC_PUBLISHED, publ->ref, |
| 335 | publ->upper, | 335 | publ->node, created_subseq); |
| 336 | TIPC_PUBLISHED, | ||
| 337 | publ->ref, | ||
| 338 | publ->node, | ||
| 339 | created_subseq); | ||
| 340 | } | 336 | } |
| 341 | return publ; | 337 | return publ; |
| 342 | } | 338 | } |
| @@ -404,13 +400,9 @@ found: | |||
| 404 | 400 | ||
| 405 | /* Notify any waiting subscriptions */ | 401 | /* Notify any waiting subscriptions */ |
| 406 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | 402 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { |
| 407 | tipc_subscr_report_overlap(s, | 403 | tipc_subscrp_report_overlap(s, publ->lower, publ->upper, |
| 408 | publ->lower, | 404 | TIPC_WITHDRAWN, publ->ref, |
| 409 | publ->upper, | 405 | publ->node, removed_subseq); |
| 410 | TIPC_WITHDRAWN, | ||
| 411 | publ->ref, | ||
| 412 | publ->node, | ||
| 413 | removed_subseq); | ||
| 414 | } | 406 | } |
| 415 | 407 | ||
| 416 | return publ; | 408 | return publ; |
| @@ -432,19 +424,17 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, | |||
| 432 | return; | 424 | return; |
| 433 | 425 | ||
| 434 | while (sseq != &nseq->sseqs[nseq->first_free]) { | 426 | while (sseq != &nseq->sseqs[nseq->first_free]) { |
| 435 | if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { | 427 | if (tipc_subscrp_check_overlap(s, sseq->lower, sseq->upper)) { |
| 436 | struct publication *crs; | 428 | struct publication *crs; |
| 437 | struct name_info *info = sseq->info; | 429 | struct name_info *info = sseq->info; |
| 438 | int must_report = 1; | 430 | int must_report = 1; |
| 439 | 431 | ||
| 440 | list_for_each_entry(crs, &info->zone_list, zone_list) { | 432 | list_for_each_entry(crs, &info->zone_list, zone_list) { |
| 441 | tipc_subscr_report_overlap(s, | 433 | tipc_subscrp_report_overlap(s, sseq->lower, |
| 442 | sseq->lower, | 434 | sseq->upper, |
| 443 | sseq->upper, | 435 | TIPC_PUBLISHED, |
| 444 | TIPC_PUBLISHED, | 436 | crs->ref, crs->node, |
| 445 | crs->ref, | 437 | must_report); |
| 446 | crs->node, | ||
| 447 | must_report); | ||
| 448 | must_report = 0; | 438 | must_report = 0; |
| 449 | } | 439 | } |
| 450 | } | 440 | } |
diff --git a/net/tipc/net.c b/net/tipc/net.c index a54f3cbe2246..d6d1399ae229 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include "subscr.h" | 40 | #include "subscr.h" |
| 41 | #include "socket.h" | 41 | #include "socket.h" |
| 42 | #include "node.h" | 42 | #include "node.h" |
| 43 | #include "bcast.h" | ||
| 43 | 44 | ||
| 44 | static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { | 45 | static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { |
| 45 | [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, | 46 | [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index ce9121e8e990..53e0fee80086 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
| @@ -55,6 +55,7 @@ struct tipc_nl_compat_msg { | |||
| 55 | int rep_type; | 55 | int rep_type; |
| 56 | int rep_size; | 56 | int rep_size; |
| 57 | int req_type; | 57 | int req_type; |
| 58 | struct net *net; | ||
| 58 | struct sk_buff *rep; | 59 | struct sk_buff *rep; |
| 59 | struct tlv_desc *req; | 60 | struct tlv_desc *req; |
| 60 | struct sock *dst_sk; | 61 | struct sock *dst_sk; |
| @@ -68,7 +69,8 @@ struct tipc_nl_compat_cmd_dump { | |||
| 68 | 69 | ||
| 69 | struct tipc_nl_compat_cmd_doit { | 70 | struct tipc_nl_compat_cmd_doit { |
| 70 | int (*doit)(struct sk_buff *skb, struct genl_info *info); | 71 | int (*doit)(struct sk_buff *skb, struct genl_info *info); |
| 71 | int (*transcode)(struct sk_buff *skb, struct tipc_nl_compat_msg *msg); | 72 | int (*transcode)(struct tipc_nl_compat_cmd_doit *cmd, |
| 73 | struct sk_buff *skb, struct tipc_nl_compat_msg *msg); | ||
| 72 | }; | 74 | }; |
| 73 | 75 | ||
| 74 | static int tipc_skb_tailroom(struct sk_buff *skb) | 76 | static int tipc_skb_tailroom(struct sk_buff *skb) |
| @@ -281,7 +283,7 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 281 | if (!trans_buf) | 283 | if (!trans_buf) |
| 282 | return -ENOMEM; | 284 | return -ENOMEM; |
| 283 | 285 | ||
| 284 | err = (*cmd->transcode)(trans_buf, msg); | 286 | err = (*cmd->transcode)(cmd, trans_buf, msg); |
| 285 | if (err) | 287 | if (err) |
| 286 | goto trans_out; | 288 | goto trans_out; |
| 287 | 289 | ||
| @@ -353,7 +355,8 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg, | |||
| 353 | nla_len(bearer[TIPC_NLA_BEARER_NAME])); | 355 | nla_len(bearer[TIPC_NLA_BEARER_NAME])); |
| 354 | } | 356 | } |
| 355 | 357 | ||
| 356 | static int tipc_nl_compat_bearer_enable(struct sk_buff *skb, | 358 | static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd, |
| 359 | struct sk_buff *skb, | ||
| 357 | struct tipc_nl_compat_msg *msg) | 360 | struct tipc_nl_compat_msg *msg) |
| 358 | { | 361 | { |
| 359 | struct nlattr *prop; | 362 | struct nlattr *prop; |
| @@ -385,7 +388,8 @@ static int tipc_nl_compat_bearer_enable(struct sk_buff *skb, | |||
| 385 | return 0; | 388 | return 0; |
| 386 | } | 389 | } |
| 387 | 390 | ||
| 388 | static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, | 391 | static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd, |
| 392 | struct sk_buff *skb, | ||
| 389 | struct tipc_nl_compat_msg *msg) | 393 | struct tipc_nl_compat_msg *msg) |
| 390 | { | 394 | { |
| 391 | char *name; | 395 | char *name; |
| @@ -576,11 +580,81 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, | |||
| 576 | &link_info, sizeof(link_info)); | 580 | &link_info, sizeof(link_info)); |
| 577 | } | 581 | } |
| 578 | 582 | ||
| 579 | static int tipc_nl_compat_link_set(struct sk_buff *skb, | 583 | static int __tipc_add_link_prop(struct sk_buff *skb, |
| 580 | struct tipc_nl_compat_msg *msg) | 584 | struct tipc_nl_compat_msg *msg, |
| 585 | struct tipc_link_config *lc) | ||
| 586 | { | ||
| 587 | switch (msg->cmd) { | ||
| 588 | case TIPC_CMD_SET_LINK_PRI: | ||
| 589 | return nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value)); | ||
| 590 | case TIPC_CMD_SET_LINK_TOL: | ||
| 591 | return nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value)); | ||
| 592 | case TIPC_CMD_SET_LINK_WINDOW: | ||
| 593 | return nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value)); | ||
| 594 | } | ||
| 595 | |||
| 596 | return -EINVAL; | ||
| 597 | } | ||
| 598 | |||
| 599 | static int tipc_nl_compat_media_set(struct sk_buff *skb, | ||
| 600 | struct tipc_nl_compat_msg *msg) | ||
| 581 | { | 601 | { |
| 582 | struct nlattr *link; | ||
| 583 | struct nlattr *prop; | 602 | struct nlattr *prop; |
| 603 | struct nlattr *media; | ||
| 604 | struct tipc_link_config *lc; | ||
| 605 | |||
| 606 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | ||
| 607 | |||
| 608 | media = nla_nest_start(skb, TIPC_NLA_MEDIA); | ||
| 609 | if (!media) | ||
| 610 | return -EMSGSIZE; | ||
| 611 | |||
| 612 | if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name)) | ||
| 613 | return -EMSGSIZE; | ||
| 614 | |||
| 615 | prop = nla_nest_start(skb, TIPC_NLA_MEDIA_PROP); | ||
| 616 | if (!prop) | ||
| 617 | return -EMSGSIZE; | ||
| 618 | |||
| 619 | __tipc_add_link_prop(skb, msg, lc); | ||
| 620 | nla_nest_end(skb, prop); | ||
| 621 | nla_nest_end(skb, media); | ||
| 622 | |||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | static int tipc_nl_compat_bearer_set(struct sk_buff *skb, | ||
| 627 | struct tipc_nl_compat_msg *msg) | ||
| 628 | { | ||
| 629 | struct nlattr *prop; | ||
| 630 | struct nlattr *bearer; | ||
| 631 | struct tipc_link_config *lc; | ||
| 632 | |||
| 633 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | ||
| 634 | |||
| 635 | bearer = nla_nest_start(skb, TIPC_NLA_BEARER); | ||
| 636 | if (!bearer) | ||
| 637 | return -EMSGSIZE; | ||
| 638 | |||
| 639 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name)) | ||
| 640 | return -EMSGSIZE; | ||
| 641 | |||
| 642 | prop = nla_nest_start(skb, TIPC_NLA_BEARER_PROP); | ||
| 643 | if (!prop) | ||
| 644 | return -EMSGSIZE; | ||
| 645 | |||
| 646 | __tipc_add_link_prop(skb, msg, lc); | ||
| 647 | nla_nest_end(skb, prop); | ||
| 648 | nla_nest_end(skb, bearer); | ||
| 649 | |||
| 650 | return 0; | ||
| 651 | } | ||
| 652 | |||
| 653 | static int __tipc_nl_compat_link_set(struct sk_buff *skb, | ||
| 654 | struct tipc_nl_compat_msg *msg) | ||
| 655 | { | ||
| 656 | struct nlattr *prop; | ||
| 657 | struct nlattr *link; | ||
| 584 | struct tipc_link_config *lc; | 658 | struct tipc_link_config *lc; |
| 585 | 659 | ||
| 586 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | 660 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); |
| @@ -596,24 +670,40 @@ static int tipc_nl_compat_link_set(struct sk_buff *skb, | |||
| 596 | if (!prop) | 670 | if (!prop) |
| 597 | return -EMSGSIZE; | 671 | return -EMSGSIZE; |
| 598 | 672 | ||
| 599 | if (msg->cmd == TIPC_CMD_SET_LINK_PRI) { | 673 | __tipc_add_link_prop(skb, msg, lc); |
| 600 | if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value))) | ||
| 601 | return -EMSGSIZE; | ||
| 602 | } else if (msg->cmd == TIPC_CMD_SET_LINK_TOL) { | ||
| 603 | if (nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value))) | ||
| 604 | return -EMSGSIZE; | ||
| 605 | } else if (msg->cmd == TIPC_CMD_SET_LINK_WINDOW) { | ||
| 606 | if (nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value))) | ||
| 607 | return -EMSGSIZE; | ||
| 608 | } | ||
| 609 | |||
| 610 | nla_nest_end(skb, prop); | 674 | nla_nest_end(skb, prop); |
| 611 | nla_nest_end(skb, link); | 675 | nla_nest_end(skb, link); |
| 612 | 676 | ||
| 613 | return 0; | 677 | return 0; |
| 614 | } | 678 | } |
| 615 | 679 | ||
| 616 | static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, | 680 | static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd, |
| 681 | struct sk_buff *skb, | ||
| 682 | struct tipc_nl_compat_msg *msg) | ||
| 683 | { | ||
| 684 | struct tipc_link_config *lc; | ||
| 685 | struct tipc_bearer *bearer; | ||
| 686 | struct tipc_media *media; | ||
| 687 | |||
| 688 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | ||
| 689 | |||
| 690 | media = tipc_media_find(lc->name); | ||
| 691 | if (media) { | ||
| 692 | cmd->doit = &tipc_nl_media_set; | ||
| 693 | return tipc_nl_compat_media_set(skb, msg); | ||
| 694 | } | ||
| 695 | |||
| 696 | bearer = tipc_bearer_find(msg->net, lc->name); | ||
| 697 | if (bearer) { | ||
| 698 | cmd->doit = &tipc_nl_bearer_set; | ||
| 699 | return tipc_nl_compat_bearer_set(skb, msg); | ||
| 700 | } | ||
| 701 | |||
| 702 | return __tipc_nl_compat_link_set(skb, msg); | ||
| 703 | } | ||
| 704 | |||
| 705 | static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd, | ||
| 706 | struct sk_buff *skb, | ||
| 617 | struct tipc_nl_compat_msg *msg) | 707 | struct tipc_nl_compat_msg *msg) |
| 618 | { | 708 | { |
| 619 | char *name; | 709 | char *name; |
| @@ -851,7 +941,8 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg, | |||
| 851 | sizeof(node_info)); | 941 | sizeof(node_info)); |
| 852 | } | 942 | } |
| 853 | 943 | ||
| 854 | static int tipc_nl_compat_net_set(struct sk_buff *skb, | 944 | static int tipc_nl_compat_net_set(struct tipc_nl_compat_cmd_doit *cmd, |
| 945 | struct sk_buff *skb, | ||
| 855 | struct tipc_nl_compat_msg *msg) | 946 | struct tipc_nl_compat_msg *msg) |
| 856 | { | 947 | { |
| 857 | u32 val; | 948 | u32 val; |
| @@ -1007,7 +1098,6 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
| 1007 | struct nlmsghdr *req_nlh; | 1098 | struct nlmsghdr *req_nlh; |
| 1008 | struct nlmsghdr *rep_nlh; | 1099 | struct nlmsghdr *rep_nlh; |
| 1009 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; | 1100 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; |
| 1010 | struct net *net = genl_info_net(info); | ||
| 1011 | 1101 | ||
| 1012 | memset(&msg, 0, sizeof(msg)); | 1102 | memset(&msg, 0, sizeof(msg)); |
| 1013 | 1103 | ||
| @@ -1015,6 +1105,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
| 1015 | msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; | 1105 | msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; |
| 1016 | msg.cmd = req_userhdr->cmd; | 1106 | msg.cmd = req_userhdr->cmd; |
| 1017 | msg.dst_sk = info->dst_sk; | 1107 | msg.dst_sk = info->dst_sk; |
| 1108 | msg.net = genl_info_net(info); | ||
| 1018 | 1109 | ||
| 1019 | if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { | 1110 | if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { |
| 1020 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); | 1111 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); |
| @@ -1030,7 +1121,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
| 1030 | } | 1121 | } |
| 1031 | 1122 | ||
| 1032 | err = tipc_nl_compat_handle(&msg); | 1123 | err = tipc_nl_compat_handle(&msg); |
| 1033 | if (err == -EOPNOTSUPP) | 1124 | if ((err == -EOPNOTSUPP) || (err == -EPERM)) |
| 1034 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); | 1125 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); |
| 1035 | else if (err == -EINVAL) | 1126 | else if (err == -EINVAL) |
| 1036 | msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); | 1127 | msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); |
| @@ -1043,7 +1134,7 @@ send: | |||
| 1043 | rep_nlh = nlmsg_hdr(msg.rep); | 1134 | rep_nlh = nlmsg_hdr(msg.rep); |
| 1044 | memcpy(rep_nlh, info->nlhdr, len); | 1135 | memcpy(rep_nlh, info->nlhdr, len); |
| 1045 | rep_nlh->nlmsg_len = msg.rep->len; | 1136 | rep_nlh->nlmsg_len = msg.rep->len; |
| 1046 | genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid); | 1137 | genlmsg_unicast(msg.net, msg.rep, NETLINK_CB(skb).portid); |
| 1047 | 1138 | ||
| 1048 | return err; | 1139 | return err; |
| 1049 | } | 1140 | } |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 22c059ad2999..0b1d61a5f853 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/node.c: TIPC node management routines | 2 | * net/tipc/node.c: TIPC node management routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000-2006, 2012-2014, Ericsson AB | 4 | * Copyright (c) 2000-2006, 2012-2015, Ericsson AB |
| 5 | * Copyright (c) 2005-2006, 2010-2014, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2014, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "node.h" | 39 | #include "node.h" |
| 40 | #include "name_distr.h" | 40 | #include "name_distr.h" |
| 41 | #include "socket.h" | 41 | #include "socket.h" |
| 42 | #include "bcast.h" | ||
| 42 | 43 | ||
| 43 | static void node_lost_contact(struct tipc_node *n_ptr); | 44 | static void node_lost_contact(struct tipc_node *n_ptr); |
| 44 | static void node_established_contact(struct tipc_node *n_ptr); | 45 | static void node_established_contact(struct tipc_node *n_ptr); |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 02d5c20dc551..5a834cf142c8 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
| @@ -45,8 +45,6 @@ | |||
| 45 | /* Out-of-range value for node signature */ | 45 | /* Out-of-range value for node signature */ |
| 46 | #define INVALID_NODE_SIG 0x10000 | 46 | #define INVALID_NODE_SIG 0x10000 |
| 47 | 47 | ||
| 48 | #define NODE_HTABLE_SIZE 512 | ||
| 49 | |||
| 50 | /* Flags used to take different actions according to flag type | 48 | /* Flags used to take different actions according to flag type |
| 51 | * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down | 49 | * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down |
| 52 | * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down | 50 | * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down |
diff --git a/net/tipc/server.c b/net/tipc/server.c index 77ff03ed1e18..922e04a43396 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
| @@ -309,6 +309,10 @@ static int tipc_accept_from_sock(struct tipc_conn *con) | |||
| 309 | 309 | ||
| 310 | /* Notify that new connection is incoming */ | 310 | /* Notify that new connection is incoming */ |
| 311 | newcon->usr_data = s->tipc_conn_new(newcon->conid); | 311 | newcon->usr_data = s->tipc_conn_new(newcon->conid); |
| 312 | if (!newcon->usr_data) { | ||
| 313 | sock_release(newsock); | ||
| 314 | return -ENOMEM; | ||
| 315 | } | ||
| 312 | 316 | ||
| 313 | /* Wake up receive process in case of 'SYN+' message */ | 317 | /* Wake up receive process in case of 'SYN+' message */ |
| 314 | newsock->sk->sk_data_ready(newsock->sk); | 318 | newsock->sk->sk_data_ready(newsock->sk); |
| @@ -321,7 +325,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
| 321 | struct socket *sock = NULL; | 325 | struct socket *sock = NULL; |
| 322 | int ret; | 326 | int ret; |
| 323 | 327 | ||
| 324 | ret = __sock_create(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1); | 328 | ret = sock_create_kern(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock); |
| 325 | if (ret < 0) | 329 | if (ret < 0) |
| 326 | return NULL; | 330 | return NULL; |
| 327 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, | 331 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index f485600c4507..46b6ed534ef2 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include "link.h" | 41 | #include "link.h" |
| 42 | #include "name_distr.h" | 42 | #include "name_distr.h" |
| 43 | #include "socket.h" | 43 | #include "socket.h" |
| 44 | #include "bcast.h" | ||
| 44 | 45 | ||
| 45 | #define SS_LISTENING -1 /* socket is listening */ | 46 | #define SS_LISTENING -1 /* socket is listening */ |
| 46 | #define SS_READY -2 /* socket is connectionless */ | 47 | #define SS_READY -2 /* socket is connectionless */ |
| @@ -342,7 +343,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
| 342 | } | 343 | } |
| 343 | 344 | ||
| 344 | /* Allocate socket's protocol area */ | 345 | /* Allocate socket's protocol area */ |
| 345 | sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); | 346 | sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, kern); |
| 346 | if (sk == NULL) | 347 | if (sk == NULL) |
| 347 | return -ENOMEM; | 348 | return -ENOMEM; |
| 348 | 349 | ||
| @@ -409,7 +410,7 @@ static int tipc_release(struct socket *sock) | |||
| 409 | struct net *net; | 410 | struct net *net; |
| 410 | struct tipc_sock *tsk; | 411 | struct tipc_sock *tsk; |
| 411 | struct sk_buff *skb; | 412 | struct sk_buff *skb; |
| 412 | u32 dnode, probing_state; | 413 | u32 dnode; |
| 413 | 414 | ||
| 414 | /* | 415 | /* |
| 415 | * Exit if socket isn't fully initialized (occurs when a failed accept() | 416 | * Exit if socket isn't fully initialized (occurs when a failed accept() |
| @@ -447,10 +448,7 @@ static int tipc_release(struct socket *sock) | |||
| 447 | } | 448 | } |
| 448 | 449 | ||
| 449 | tipc_sk_withdraw(tsk, 0, NULL); | 450 | tipc_sk_withdraw(tsk, 0, NULL); |
| 450 | probing_state = tsk->probing_state; | 451 | sk_stop_timer(sk, &sk->sk_timer); |
| 451 | if (del_timer_sync(&sk->sk_timer) && | ||
| 452 | probing_state != TIPC_CONN_PROBING) | ||
| 453 | sock_put(sk); | ||
| 454 | tipc_sk_remove(tsk); | 452 | tipc_sk_remove(tsk); |
| 455 | if (tsk->connected) { | 453 | if (tsk->connected) { |
| 456 | skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, | 454 | skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 1c147c869c2e..350cca33ee0a 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
| @@ -40,16 +40,21 @@ | |||
| 40 | 40 | ||
| 41 | /** | 41 | /** |
| 42 | * struct tipc_subscriber - TIPC network topology subscriber | 42 | * struct tipc_subscriber - TIPC network topology subscriber |
| 43 | * @kref: reference counter to tipc_subscription object | ||
| 43 | * @conid: connection identifier to server connecting to subscriber | 44 | * @conid: connection identifier to server connecting to subscriber |
| 44 | * @lock: control access to subscriber | 45 | * @lock: control access to subscriber |
| 45 | * @subscription_list: list of subscription objects for this subscriber | 46 | * @subscrp_list: list of subscription objects for this subscriber |
| 46 | */ | 47 | */ |
| 47 | struct tipc_subscriber { | 48 | struct tipc_subscriber { |
| 49 | struct kref kref; | ||
| 48 | int conid; | 50 | int conid; |
| 49 | spinlock_t lock; | 51 | spinlock_t lock; |
| 50 | struct list_head subscription_list; | 52 | struct list_head subscrp_list; |
| 51 | }; | 53 | }; |
| 52 | 54 | ||
| 55 | static void tipc_subscrp_delete(struct tipc_subscription *sub); | ||
| 56 | static void tipc_subscrb_put(struct tipc_subscriber *subscriber); | ||
| 57 | |||
| 53 | /** | 58 | /** |
| 54 | * htohl - convert value to endianness used by destination | 59 | * htohl - convert value to endianness used by destination |
| 55 | * @in: value to convert | 60 | * @in: value to convert |
| @@ -62,9 +67,9 @@ static u32 htohl(u32 in, int swap) | |||
| 62 | return swap ? swab32(in) : in; | 67 | return swap ? swab32(in) : in; |
| 63 | } | 68 | } |
| 64 | 69 | ||
| 65 | static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | 70 | static void tipc_subscrp_send_event(struct tipc_subscription *sub, |
| 66 | u32 found_upper, u32 event, u32 port_ref, | 71 | u32 found_lower, u32 found_upper, |
| 67 | u32 node) | 72 | u32 event, u32 port_ref, u32 node) |
| 68 | { | 73 | { |
| 69 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | 74 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); |
| 70 | struct tipc_subscriber *subscriber = sub->subscriber; | 75 | struct tipc_subscriber *subscriber = sub->subscriber; |
| @@ -82,12 +87,13 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | |||
| 82 | } | 87 | } |
| 83 | 88 | ||
| 84 | /** | 89 | /** |
| 85 | * tipc_subscr_overlap - test for subscription overlap with the given values | 90 | * tipc_subscrp_check_overlap - test for subscription overlap with the |
| 91 | * given values | ||
| 86 | * | 92 | * |
| 87 | * Returns 1 if there is overlap, otherwise 0. | 93 | * Returns 1 if there is overlap, otherwise 0. |
| 88 | */ | 94 | */ |
| 89 | int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, | 95 | int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, |
| 90 | u32 found_upper) | 96 | u32 found_upper) |
| 91 | { | 97 | { |
| 92 | if (found_lower < sub->seq.lower) | 98 | if (found_lower < sub->seq.lower) |
| 93 | found_lower = sub->seq.lower; | 99 | found_lower = sub->seq.lower; |
| @@ -98,138 +104,121 @@ int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, | |||
| 98 | return 1; | 104 | return 1; |
| 99 | } | 105 | } |
| 100 | 106 | ||
| 101 | /** | 107 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, |
| 102 | * tipc_subscr_report_overlap - issue event if there is subscription overlap | 108 | u32 found_upper, u32 event, u32 port_ref, |
| 103 | * | 109 | u32 node, int must) |
| 104 | * Protected by nameseq.lock in name_table.c | ||
| 105 | */ | ||
| 106 | void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, | ||
| 107 | u32 found_upper, u32 event, u32 port_ref, | ||
| 108 | u32 node, int must) | ||
| 109 | { | 110 | { |
| 110 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) | 111 | if (!tipc_subscrp_check_overlap(sub, found_lower, found_upper)) |
| 111 | return; | 112 | return; |
| 112 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) | 113 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) |
| 113 | return; | 114 | return; |
| 114 | 115 | ||
| 115 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | 116 | tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, |
| 117 | node); | ||
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | static void subscr_timeout(unsigned long data) | 120 | static void tipc_subscrp_timeout(unsigned long data) |
| 119 | { | 121 | { |
| 120 | struct tipc_subscription *sub = (struct tipc_subscription *)data; | 122 | struct tipc_subscription *sub = (struct tipc_subscription *)data; |
| 121 | struct tipc_subscriber *subscriber = sub->subscriber; | 123 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 122 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | ||
| 123 | 124 | ||
| 124 | /* The spin lock per subscriber is used to protect its members */ | 125 | /* Notify subscriber of timeout */ |
| 125 | spin_lock_bh(&subscriber->lock); | 126 | tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, |
| 127 | TIPC_SUBSCR_TIMEOUT, 0, 0); | ||
| 126 | 128 | ||
| 127 | /* Validate timeout (in case subscription is being cancelled) */ | 129 | spin_lock_bh(&subscriber->lock); |
| 128 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 130 | tipc_subscrp_delete(sub); |
| 129 | spin_unlock_bh(&subscriber->lock); | 131 | spin_unlock_bh(&subscriber->lock); |
| 130 | return; | ||
| 131 | } | ||
| 132 | 132 | ||
| 133 | /* Unlink subscription from name table */ | 133 | tipc_subscrb_put(subscriber); |
| 134 | tipc_nametbl_unsubscribe(sub); | 134 | } |
| 135 | 135 | ||
| 136 | /* Unlink subscription from subscriber */ | 136 | static void tipc_subscrb_kref_release(struct kref *kref) |
| 137 | list_del(&sub->subscription_list); | 137 | { |
| 138 | struct tipc_subscriber *subcriber = container_of(kref, | ||
| 139 | struct tipc_subscriber, kref); | ||
| 138 | 140 | ||
| 139 | spin_unlock_bh(&subscriber->lock); | 141 | kfree(subcriber); |
| 142 | } | ||
| 140 | 143 | ||
| 141 | /* Notify subscriber of timeout */ | 144 | static void tipc_subscrb_put(struct tipc_subscriber *subscriber) |
| 142 | subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, | 145 | { |
| 143 | TIPC_SUBSCR_TIMEOUT, 0, 0); | 146 | kref_put(&subscriber->kref, tipc_subscrb_kref_release); |
| 147 | } | ||
| 144 | 148 | ||
| 145 | /* Now destroy subscription */ | 149 | static void tipc_subscrb_get(struct tipc_subscriber *subscriber) |
| 146 | kfree(sub); | 150 | { |
| 147 | atomic_dec(&tn->subscription_count); | 151 | kref_get(&subscriber->kref); |
| 148 | } | 152 | } |
| 149 | 153 | ||
| 150 | /** | 154 | static struct tipc_subscriber *tipc_subscrb_create(int conid) |
| 151 | * subscr_del - delete a subscription within a subscription list | ||
| 152 | * | ||
| 153 | * Called with subscriber lock held. | ||
| 154 | */ | ||
| 155 | static void subscr_del(struct tipc_subscription *sub) | ||
| 156 | { | 155 | { |
| 157 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | 156 | struct tipc_subscriber *subscriber; |
| 158 | 157 | ||
| 159 | tipc_nametbl_unsubscribe(sub); | 158 | subscriber = kzalloc(sizeof(*subscriber), GFP_ATOMIC); |
| 160 | list_del(&sub->subscription_list); | 159 | if (!subscriber) { |
| 161 | kfree(sub); | 160 | pr_warn("Subscriber rejected, no memory\n"); |
| 162 | atomic_dec(&tn->subscription_count); | 161 | return NULL; |
| 162 | } | ||
| 163 | kref_init(&subscriber->kref); | ||
| 164 | INIT_LIST_HEAD(&subscriber->subscrp_list); | ||
| 165 | subscriber->conid = conid; | ||
| 166 | spin_lock_init(&subscriber->lock); | ||
| 167 | |||
| 168 | return subscriber; | ||
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | static void subscr_release(struct tipc_subscriber *subscriber) | 171 | static void tipc_subscrb_delete(struct tipc_subscriber *subscriber) |
| 166 | { | 172 | { |
| 167 | struct tipc_subscription *sub; | 173 | struct tipc_subscription *sub, *temp; |
| 168 | struct tipc_subscription *sub_temp; | ||
| 169 | 174 | ||
| 170 | spin_lock_bh(&subscriber->lock); | 175 | spin_lock_bh(&subscriber->lock); |
| 171 | |||
| 172 | /* Destroy any existing subscriptions for subscriber */ | 176 | /* Destroy any existing subscriptions for subscriber */ |
| 173 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 177 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, |
| 174 | subscription_list) { | 178 | subscrp_list) { |
| 175 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 179 | if (del_timer(&sub->timer)) { |
| 176 | spin_unlock_bh(&subscriber->lock); | 180 | tipc_subscrp_delete(sub); |
| 177 | del_timer_sync(&sub->timer); | 181 | tipc_subscrb_put(subscriber); |
| 178 | spin_lock_bh(&subscriber->lock); | ||
| 179 | } | 182 | } |
| 180 | subscr_del(sub); | ||
| 181 | } | 183 | } |
| 182 | spin_unlock_bh(&subscriber->lock); | 184 | spin_unlock_bh(&subscriber->lock); |
| 183 | 185 | ||
| 184 | /* Now destroy subscriber */ | 186 | tipc_subscrb_put(subscriber); |
| 185 | kfree(subscriber); | ||
| 186 | } | 187 | } |
| 187 | 188 | ||
| 188 | /** | 189 | static void tipc_subscrp_delete(struct tipc_subscription *sub) |
| 189 | * subscr_cancel - handle subscription cancellation request | ||
| 190 | * | ||
| 191 | * Called with subscriber lock held. Routine must temporarily release lock | ||
| 192 | * to enable the subscription timeout routine to finish without deadlocking; | ||
| 193 | * the lock is then reclaimed to allow caller to release it upon return. | ||
| 194 | * | ||
| 195 | * Note that fields of 's' use subscriber's endianness! | ||
| 196 | */ | ||
| 197 | static void subscr_cancel(struct tipc_subscr *s, | ||
| 198 | struct tipc_subscriber *subscriber) | ||
| 199 | { | 190 | { |
| 200 | struct tipc_subscription *sub; | 191 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); |
| 201 | struct tipc_subscription *sub_temp; | 192 | |
| 202 | int found = 0; | 193 | tipc_nametbl_unsubscribe(sub); |
| 194 | list_del(&sub->subscrp_list); | ||
| 195 | kfree(sub); | ||
| 196 | atomic_dec(&tn->subscription_count); | ||
| 197 | } | ||
| 203 | 198 | ||
| 199 | static void tipc_subscrp_cancel(struct tipc_subscr *s, | ||
| 200 | struct tipc_subscriber *subscriber) | ||
| 201 | { | ||
| 202 | struct tipc_subscription *sub, *temp; | ||
| 203 | |||
| 204 | spin_lock_bh(&subscriber->lock); | ||
| 204 | /* Find first matching subscription, exit if not found */ | 205 | /* Find first matching subscription, exit if not found */ |
| 205 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 206 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, |
| 206 | subscription_list) { | 207 | subscrp_list) { |
| 207 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { | 208 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { |
| 208 | found = 1; | 209 | if (del_timer(&sub->timer)) { |
| 210 | tipc_subscrp_delete(sub); | ||
| 211 | tipc_subscrb_put(subscriber); | ||
| 212 | } | ||
| 209 | break; | 213 | break; |
| 210 | } | 214 | } |
| 211 | } | 215 | } |
| 212 | if (!found) | 216 | spin_unlock_bh(&subscriber->lock); |
| 213 | return; | ||
| 214 | |||
| 215 | /* Cancel subscription timer (if used), then delete subscription */ | ||
| 216 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
| 217 | sub->timeout = TIPC_WAIT_FOREVER; | ||
| 218 | spin_unlock_bh(&subscriber->lock); | ||
| 219 | del_timer_sync(&sub->timer); | ||
| 220 | spin_lock_bh(&subscriber->lock); | ||
| 221 | } | ||
| 222 | subscr_del(sub); | ||
| 223 | } | 217 | } |
| 224 | 218 | ||
| 225 | /** | 219 | static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, |
| 226 | * subscr_subscribe - create subscription for subscriber | 220 | struct tipc_subscriber *subscriber, |
| 227 | * | 221 | struct tipc_subscription **sub_p) |
| 228 | * Called with subscriber lock held. | ||
| 229 | */ | ||
| 230 | static int subscr_subscribe(struct net *net, struct tipc_subscr *s, | ||
| 231 | struct tipc_subscriber *subscriber, | ||
| 232 | struct tipc_subscription **sub_p) | ||
| 233 | { | 222 | { |
| 234 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 223 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 235 | struct tipc_subscription *sub; | 224 | struct tipc_subscription *sub; |
| @@ -241,7 +230,7 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s, | |||
| 241 | /* Detect & process a subscription cancellation request */ | 230 | /* Detect & process a subscription cancellation request */ |
| 242 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 231 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
| 243 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | 232 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
| 244 | subscr_cancel(s, subscriber); | 233 | tipc_subscrp_cancel(s, subscriber); |
| 245 | return 0; | 234 | return 0; |
| 246 | } | 235 | } |
| 247 | 236 | ||
| @@ -273,62 +262,51 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s, | |||
| 273 | kfree(sub); | 262 | kfree(sub); |
| 274 | return -EINVAL; | 263 | return -EINVAL; |
| 275 | } | 264 | } |
| 276 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 265 | spin_lock_bh(&subscriber->lock); |
| 266 | list_add(&sub->subscrp_list, &subscriber->subscrp_list); | ||
| 267 | spin_unlock_bh(&subscriber->lock); | ||
| 277 | sub->subscriber = subscriber; | 268 | sub->subscriber = subscriber; |
| 278 | sub->swap = swap; | 269 | sub->swap = swap; |
| 279 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | 270 | memcpy(&sub->evt.s, s, sizeof(*s)); |
| 280 | atomic_inc(&tn->subscription_count); | 271 | atomic_inc(&tn->subscription_count); |
| 281 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 272 | setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); |
| 282 | setup_timer(&sub->timer, subscr_timeout, (unsigned long)sub); | 273 | if (sub->timeout != TIPC_WAIT_FOREVER) |
| 283 | mod_timer(&sub->timer, jiffies + sub->timeout); | 274 | sub->timeout += jiffies; |
| 284 | } | 275 | if (!mod_timer(&sub->timer, sub->timeout)) |
| 276 | tipc_subscrb_get(subscriber); | ||
| 285 | *sub_p = sub; | 277 | *sub_p = sub; |
| 286 | return 0; | 278 | return 0; |
| 287 | } | 279 | } |
| 288 | 280 | ||
| 289 | /* Handle one termination request for the subscriber */ | 281 | /* Handle one termination request for the subscriber */ |
| 290 | static void subscr_conn_shutdown_event(int conid, void *usr_data) | 282 | static void tipc_subscrb_shutdown_cb(int conid, void *usr_data) |
| 291 | { | 283 | { |
| 292 | subscr_release((struct tipc_subscriber *)usr_data); | 284 | tipc_subscrb_delete((struct tipc_subscriber *)usr_data); |
| 293 | } | 285 | } |
| 294 | 286 | ||
| 295 | /* Handle one request to create a new subscription for the subscriber */ | 287 | /* Handle one request to create a new subscription for the subscriber */ |
| 296 | static void subscr_conn_msg_event(struct net *net, int conid, | 288 | static void tipc_subscrb_rcv_cb(struct net *net, int conid, |
| 297 | struct sockaddr_tipc *addr, void *usr_data, | 289 | struct sockaddr_tipc *addr, void *usr_data, |
| 298 | void *buf, size_t len) | 290 | void *buf, size_t len) |
| 299 | { | 291 | { |
| 300 | struct tipc_subscriber *subscriber = usr_data; | 292 | struct tipc_subscriber *subscriber = usr_data; |
| 301 | struct tipc_subscription *sub = NULL; | 293 | struct tipc_subscription *sub = NULL; |
| 302 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 294 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 303 | 295 | ||
| 304 | spin_lock_bh(&subscriber->lock); | 296 | tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscriber, &sub); |
| 305 | subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, &sub); | ||
| 306 | if (sub) | 297 | if (sub) |
| 307 | tipc_nametbl_subscribe(sub); | 298 | tipc_nametbl_subscribe(sub); |
| 308 | else | 299 | else |
| 309 | tipc_conn_terminate(tn->topsrv, subscriber->conid); | 300 | tipc_conn_terminate(tn->topsrv, subscriber->conid); |
| 310 | spin_unlock_bh(&subscriber->lock); | ||
| 311 | } | 301 | } |
| 312 | 302 | ||
| 313 | /* Handle one request to establish a new subscriber */ | 303 | /* Handle one request to establish a new subscriber */ |
| 314 | static void *subscr_named_msg_event(int conid) | 304 | static void *tipc_subscrb_connect_cb(int conid) |
| 315 | { | 305 | { |
| 316 | struct tipc_subscriber *subscriber; | 306 | return (void *)tipc_subscrb_create(conid); |
| 317 | |||
| 318 | /* Create subscriber object */ | ||
| 319 | subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC); | ||
| 320 | if (subscriber == NULL) { | ||
| 321 | pr_warn("Subscriber rejected, no memory\n"); | ||
| 322 | return NULL; | ||
| 323 | } | ||
| 324 | INIT_LIST_HEAD(&subscriber->subscription_list); | ||
| 325 | subscriber->conid = conid; | ||
| 326 | spin_lock_init(&subscriber->lock); | ||
| 327 | |||
| 328 | return (void *)subscriber; | ||
| 329 | } | 307 | } |
| 330 | 308 | ||
| 331 | int tipc_subscr_start(struct net *net) | 309 | int tipc_topsrv_start(struct net *net) |
| 332 | { | 310 | { |
| 333 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 311 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 334 | const char name[] = "topology_server"; | 312 | const char name[] = "topology_server"; |
| @@ -355,9 +333,9 @@ int tipc_subscr_start(struct net *net) | |||
| 355 | topsrv->imp = TIPC_CRITICAL_IMPORTANCE; | 333 | topsrv->imp = TIPC_CRITICAL_IMPORTANCE; |
| 356 | topsrv->type = SOCK_SEQPACKET; | 334 | topsrv->type = SOCK_SEQPACKET; |
| 357 | topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); | 335 | topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); |
| 358 | topsrv->tipc_conn_recvmsg = subscr_conn_msg_event; | 336 | topsrv->tipc_conn_recvmsg = tipc_subscrb_rcv_cb; |
| 359 | topsrv->tipc_conn_new = subscr_named_msg_event; | 337 | topsrv->tipc_conn_new = tipc_subscrb_connect_cb; |
| 360 | topsrv->tipc_conn_shutdown = subscr_conn_shutdown_event; | 338 | topsrv->tipc_conn_shutdown = tipc_subscrb_shutdown_cb; |
| 361 | 339 | ||
| 362 | strncpy(topsrv->name, name, strlen(name) + 1); | 340 | strncpy(topsrv->name, name, strlen(name) + 1); |
| 363 | tn->topsrv = topsrv; | 341 | tn->topsrv = topsrv; |
| @@ -366,7 +344,7 @@ int tipc_subscr_start(struct net *net) | |||
| 366 | return tipc_server_start(topsrv); | 344 | return tipc_server_start(topsrv); |
| 367 | } | 345 | } |
| 368 | 346 | ||
| 369 | void tipc_subscr_stop(struct net *net) | 347 | void tipc_topsrv_stop(struct net *net) |
| 370 | { | 348 | { |
| 371 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 349 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 372 | struct tipc_server *topsrv = tn->topsrv; | 350 | struct tipc_server *topsrv = tn->topsrv; |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 33488bd9fe3c..92ee18cc5fe6 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
| @@ -54,7 +54,7 @@ struct tipc_subscriber; | |||
| 54 | * @filter: event filtering to be done for subscription | 54 | * @filter: event filtering to be done for subscription |
| 55 | * @timer: timer governing subscription duration (optional) | 55 | * @timer: timer governing subscription duration (optional) |
| 56 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 56 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
| 57 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | 57 | * @subscrp_list: adjacent subscriptions in subscriber's subscription list |
| 58 | * @server_ref: object reference of server port associated with subscription | 58 | * @server_ref: object reference of server port associated with subscription |
| 59 | * @swap: indicates if subscriber uses opposite endianness in its messages | 59 | * @swap: indicates if subscriber uses opposite endianness in its messages |
| 60 | * @evt: template for events generated by subscription | 60 | * @evt: template for events generated by subscription |
| @@ -67,17 +67,17 @@ struct tipc_subscription { | |||
| 67 | u32 filter; | 67 | u32 filter; |
| 68 | struct timer_list timer; | 68 | struct timer_list timer; |
| 69 | struct list_head nameseq_list; | 69 | struct list_head nameseq_list; |
| 70 | struct list_head subscription_list; | 70 | struct list_head subscrp_list; |
| 71 | int swap; | 71 | int swap; |
| 72 | struct tipc_event evt; | 72 | struct tipc_event evt; |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, | 75 | int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, |
| 76 | u32 found_upper); | 76 | u32 found_upper); |
| 77 | void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, | 77 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, |
| 78 | u32 found_upper, u32 event, u32 port_ref, | 78 | u32 found_lower, u32 found_upper, u32 event, |
| 79 | u32 node, int must); | 79 | u32 port_ref, u32 node, int must); |
| 80 | int tipc_subscr_start(struct net *net); | 80 | int tipc_topsrv_start(struct net *net); |
| 81 | void tipc_subscr_stop(struct net *net); | 81 | void tipc_topsrv_stop(struct net *net); |
| 82 | 82 | ||
| 83 | #endif | 83 | #endif |
