diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/bearer.c | 12 | ||||
| -rw-r--r-- | net/tipc/link.c | 45 | ||||
| -rw-r--r-- | net/tipc/link.h | 3 | ||||
| -rw-r--r-- | net/tipc/node.c | 14 | ||||
| -rw-r--r-- | net/tipc/socket.c | 4 |
5 files changed, 70 insertions, 8 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 418f03d0be90..645c16052052 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -609,16 +609,18 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 609 | 609 | ||
| 610 | switch (evt) { | 610 | switch (evt) { |
| 611 | case NETDEV_CHANGE: | 611 | case NETDEV_CHANGE: |
| 612 | if (netif_carrier_ok(dev)) | 612 | if (netif_carrier_ok(dev) && netif_oper_up(dev)) { |
| 613 | test_and_set_bit_lock(0, &b->up); | ||
| 613 | break; | 614 | break; |
| 614 | /* else: fall through */ | 615 | } |
| 615 | case NETDEV_UP: | 616 | /* fall through */ |
| 616 | test_and_set_bit_lock(0, &b->up); | ||
| 617 | break; | ||
| 618 | case NETDEV_GOING_DOWN: | 617 | case NETDEV_GOING_DOWN: |
| 619 | clear_bit_unlock(0, &b->up); | 618 | clear_bit_unlock(0, &b->up); |
| 620 | tipc_reset_bearer(net, b); | 619 | tipc_reset_bearer(net, b); |
| 621 | break; | 620 | break; |
| 621 | case NETDEV_UP: | ||
| 622 | test_and_set_bit_lock(0, &b->up); | ||
| 623 | break; | ||
| 622 | case NETDEV_CHANGEMTU: | 624 | case NETDEV_CHANGEMTU: |
| 623 | if (tipc_mtu_bad(dev, 0)) { | 625 | if (tipc_mtu_bad(dev, 0)) { |
| 624 | bearer_disable(net, b); | 626 | bearer_disable(net, b); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index b1f0bee54eac..fb886b525d95 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -410,6 +410,11 @@ char *tipc_link_name(struct tipc_link *l) | |||
| 410 | return l->name; | 410 | return l->name; |
| 411 | } | 411 | } |
| 412 | 412 | ||
| 413 | u32 tipc_link_state(struct tipc_link *l) | ||
| 414 | { | ||
| 415 | return l->state; | ||
| 416 | } | ||
| 417 | |||
| 413 | /** | 418 | /** |
| 414 | * tipc_link_create - create a new link | 419 | * tipc_link_create - create a new link |
| 415 | * @n: pointer to associated node | 420 | * @n: pointer to associated node |
| @@ -841,9 +846,14 @@ void tipc_link_reset(struct tipc_link *l) | |||
| 841 | l->in_session = false; | 846 | l->in_session = false; |
| 842 | l->session++; | 847 | l->session++; |
| 843 | l->mtu = l->advertised_mtu; | 848 | l->mtu = l->advertised_mtu; |
| 849 | spin_lock_bh(&l->wakeupq.lock); | ||
| 850 | spin_lock_bh(&l->inputq->lock); | ||
| 851 | skb_queue_splice_init(&l->wakeupq, l->inputq); | ||
| 852 | spin_unlock_bh(&l->inputq->lock); | ||
| 853 | spin_unlock_bh(&l->wakeupq.lock); | ||
| 854 | |||
| 844 | __skb_queue_purge(&l->transmq); | 855 | __skb_queue_purge(&l->transmq); |
| 845 | __skb_queue_purge(&l->deferdq); | 856 | __skb_queue_purge(&l->deferdq); |
| 846 | skb_queue_splice_init(&l->wakeupq, l->inputq); | ||
| 847 | __skb_queue_purge(&l->backlogq); | 857 | __skb_queue_purge(&l->backlogq); |
| 848 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; | 858 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; |
| 849 | l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0; | 859 | l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0; |
| @@ -1380,6 +1390,36 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
| 1380 | __skb_queue_tail(xmitq, skb); | 1390 | __skb_queue_tail(xmitq, skb); |
| 1381 | } | 1391 | } |
| 1382 | 1392 | ||
| 1393 | void tipc_link_create_dummy_tnl_msg(struct tipc_link *l, | ||
| 1394 | struct sk_buff_head *xmitq) | ||
| 1395 | { | ||
| 1396 | u32 onode = tipc_own_addr(l->net); | ||
| 1397 | struct tipc_msg *hdr, *ihdr; | ||
| 1398 | struct sk_buff_head tnlq; | ||
| 1399 | struct sk_buff *skb; | ||
| 1400 | u32 dnode = l->addr; | ||
| 1401 | |||
| 1402 | skb_queue_head_init(&tnlq); | ||
| 1403 | skb = tipc_msg_create(TUNNEL_PROTOCOL, FAILOVER_MSG, | ||
| 1404 | INT_H_SIZE, BASIC_H_SIZE, | ||
| 1405 | dnode, onode, 0, 0, 0); | ||
| 1406 | if (!skb) { | ||
| 1407 | pr_warn("%sunable to create tunnel packet\n", link_co_err); | ||
| 1408 | return; | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | hdr = buf_msg(skb); | ||
| 1412 | msg_set_msgcnt(hdr, 1); | ||
| 1413 | msg_set_bearer_id(hdr, l->peer_bearer_id); | ||
| 1414 | |||
| 1415 | ihdr = (struct tipc_msg *)msg_data(hdr); | ||
| 1416 | tipc_msg_init(onode, ihdr, TIPC_LOW_IMPORTANCE, TIPC_DIRECT_MSG, | ||
| 1417 | BASIC_H_SIZE, dnode); | ||
| 1418 | msg_set_errcode(ihdr, TIPC_ERR_NO_PORT); | ||
| 1419 | __skb_queue_tail(&tnlq, skb); | ||
| 1420 | tipc_link_xmit(l, &tnlq, xmitq); | ||
| 1421 | } | ||
| 1422 | |||
| 1383 | /* tipc_link_tnl_prepare(): prepare and return a list of tunnel packets | 1423 | /* tipc_link_tnl_prepare(): prepare and return a list of tunnel packets |
| 1384 | * with contents of the link's transmit and backlog queues. | 1424 | * with contents of the link's transmit and backlog queues. |
| 1385 | */ | 1425 | */ |
| @@ -1476,6 +1516,9 @@ bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr) | |||
| 1476 | return false; | 1516 | return false; |
| 1477 | if (session != curr_session) | 1517 | if (session != curr_session) |
| 1478 | return false; | 1518 | return false; |
| 1519 | /* Extra sanity check */ | ||
| 1520 | if (!link_is_up(l) && msg_ack(hdr)) | ||
| 1521 | return false; | ||
| 1479 | if (!(l->peer_caps & TIPC_LINK_PROTO_SEQNO)) | 1522 | if (!(l->peer_caps & TIPC_LINK_PROTO_SEQNO)) |
| 1480 | return true; | 1523 | return true; |
| 1481 | /* Accept only STATE with new sequence number */ | 1524 | /* Accept only STATE with new sequence number */ |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 7bc494a33fdf..90488c538a4e 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
| @@ -88,6 +88,8 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, | |||
| 88 | struct tipc_link **link); | 88 | struct tipc_link **link); |
| 89 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | 89 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, |
| 90 | int mtyp, struct sk_buff_head *xmitq); | 90 | int mtyp, struct sk_buff_head *xmitq); |
| 91 | void tipc_link_create_dummy_tnl_msg(struct tipc_link *tnl, | ||
| 92 | struct sk_buff_head *xmitq); | ||
| 91 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); | 93 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); |
| 92 | int tipc_link_fsm_evt(struct tipc_link *l, int evt); | 94 | int tipc_link_fsm_evt(struct tipc_link *l, int evt); |
| 93 | bool tipc_link_is_up(struct tipc_link *l); | 95 | bool tipc_link_is_up(struct tipc_link *l); |
| @@ -107,6 +109,7 @@ u16 tipc_link_rcv_nxt(struct tipc_link *l); | |||
| 107 | u16 tipc_link_acked(struct tipc_link *l); | 109 | u16 tipc_link_acked(struct tipc_link *l); |
| 108 | u32 tipc_link_id(struct tipc_link *l); | 110 | u32 tipc_link_id(struct tipc_link *l); |
| 109 | char *tipc_link_name(struct tipc_link *l); | 111 | char *tipc_link_name(struct tipc_link *l); |
| 112 | u32 tipc_link_state(struct tipc_link *l); | ||
| 110 | char tipc_link_plane(struct tipc_link *l); | 113 | char tipc_link_plane(struct tipc_link *l); |
| 111 | int tipc_link_prio(struct tipc_link *l); | 114 | int tipc_link_prio(struct tipc_link *l); |
| 112 | int tipc_link_window(struct tipc_link *l); | 115 | int tipc_link_window(struct tipc_link *l); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 68014f1b6976..2afc4f8c37a7 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -111,6 +111,7 @@ struct tipc_node { | |||
| 111 | int action_flags; | 111 | int action_flags; |
| 112 | struct list_head list; | 112 | struct list_head list; |
| 113 | int state; | 113 | int state; |
| 114 | bool failover_sent; | ||
| 114 | u16 sync_point; | 115 | u16 sync_point; |
| 115 | int link_cnt; | 116 | int link_cnt; |
| 116 | u16 working_links; | 117 | u16 working_links; |
| @@ -680,6 +681,7 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
| 680 | *slot0 = bearer_id; | 681 | *slot0 = bearer_id; |
| 681 | *slot1 = bearer_id; | 682 | *slot1 = bearer_id; |
| 682 | tipc_node_fsm_evt(n, SELF_ESTABL_CONTACT_EVT); | 683 | tipc_node_fsm_evt(n, SELF_ESTABL_CONTACT_EVT); |
| 684 | n->failover_sent = false; | ||
| 683 | n->action_flags |= TIPC_NOTIFY_NODE_UP; | 685 | n->action_flags |= TIPC_NOTIFY_NODE_UP; |
| 684 | tipc_link_set_active(nl, true); | 686 | tipc_link_set_active(nl, true); |
| 685 | tipc_bcast_add_peer(n->net, nl, xmitq); | 687 | tipc_bcast_add_peer(n->net, nl, xmitq); |
| @@ -911,6 +913,7 @@ void tipc_node_check_dest(struct net *net, u32 addr, | |||
| 911 | bool reset = true; | 913 | bool reset = true; |
| 912 | char *if_name; | 914 | char *if_name; |
| 913 | unsigned long intv; | 915 | unsigned long intv; |
| 916 | u16 session; | ||
| 914 | 917 | ||
| 915 | *dupl_addr = false; | 918 | *dupl_addr = false; |
| 916 | *respond = false; | 919 | *respond = false; |
| @@ -997,9 +1000,10 @@ void tipc_node_check_dest(struct net *net, u32 addr, | |||
| 997 | goto exit; | 1000 | goto exit; |
| 998 | 1001 | ||
| 999 | if_name = strchr(b->name, ':') + 1; | 1002 | if_name = strchr(b->name, ':') + 1; |
| 1003 | get_random_bytes(&session, sizeof(u16)); | ||
| 1000 | if (!tipc_link_create(net, if_name, b->identity, b->tolerance, | 1004 | if (!tipc_link_create(net, if_name, b->identity, b->tolerance, |
| 1001 | b->net_plane, b->mtu, b->priority, | 1005 | b->net_plane, b->mtu, b->priority, |
| 1002 | b->window, mod(tipc_net(net)->random), | 1006 | b->window, session, |
| 1003 | tipc_own_addr(net), addr, peer_id, | 1007 | tipc_own_addr(net), addr, peer_id, |
| 1004 | n->capabilities, | 1008 | n->capabilities, |
| 1005 | tipc_bc_sndlink(n->net), n->bc_entry.link, | 1009 | tipc_bc_sndlink(n->net), n->bc_entry.link, |
| @@ -1615,6 +1619,14 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
| 1615 | tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl), | 1619 | tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl), |
| 1616 | tipc_link_inputq(l)); | 1620 | tipc_link_inputq(l)); |
| 1617 | } | 1621 | } |
| 1622 | /* If parallel link was already down, and this happened before | ||
| 1623 | * the tunnel link came up, FAILOVER was never sent. Ensure that | ||
| 1624 | * FAILOVER is sent to get peer out of NODE_FAILINGOVER state. | ||
| 1625 | */ | ||
| 1626 | if (n->state != NODE_FAILINGOVER && !n->failover_sent) { | ||
| 1627 | tipc_link_create_dummy_tnl_msg(l, xmitq); | ||
| 1628 | n->failover_sent = true; | ||
| 1629 | } | ||
| 1618 | /* If pkts arrive out of order, use lowest calculated syncpt */ | 1630 | /* If pkts arrive out of order, use lowest calculated syncpt */ |
| 1619 | if (less(syncpt, n->sync_point)) | 1631 | if (less(syncpt, n->sync_point)) |
| 1620 | n->sync_point = syncpt; | 1632 | n->sync_point = syncpt; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3f03ddd0e35b..b6f99b021d09 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -1419,8 +1419,10 @@ static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen) | |||
| 1419 | /* Handle implicit connection setup */ | 1419 | /* Handle implicit connection setup */ |
| 1420 | if (unlikely(dest)) { | 1420 | if (unlikely(dest)) { |
| 1421 | rc = __tipc_sendmsg(sock, m, dlen); | 1421 | rc = __tipc_sendmsg(sock, m, dlen); |
| 1422 | if (dlen && (dlen == rc)) | 1422 | if (dlen && dlen == rc) { |
| 1423 | tsk->peer_caps = tipc_node_get_capabilities(net, dnode); | ||
| 1423 | tsk->snt_unacked = tsk_inc(tsk, dlen + msg_hdr_sz(hdr)); | 1424 | tsk->snt_unacked = tsk_inc(tsk, dlen + msg_hdr_sz(hdr)); |
| 1425 | } | ||
| 1424 | return rc; | 1426 | return rc; |
| 1425 | } | 1427 | } |
| 1426 | 1428 | ||
