diff options
Diffstat (limited to 'net/tipc/port.c')
-rw-r--r-- | net/tipc/port.c | 299 |
1 files changed, 1 insertions, 298 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c index 18098cac62f2..0651522c9435 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/port.c: TIPC port code | 2 | * net/tipc/port.c: TIPC port code |
3 | * | 3 | * |
4 | * Copyright (c) 1992-2007, Ericsson AB | 4 | * Copyright (c) 1992-2007, Ericsson AB |
5 | * Copyright (c) 2004-2008, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2004-2008, 2010-2013, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -46,11 +46,7 @@ | |||
46 | 46 | ||
47 | #define MAX_REJECT_SIZE 1024 | 47 | #define MAX_REJECT_SIZE 1024 |
48 | 48 | ||
49 | static struct sk_buff *msg_queue_head; | ||
50 | static struct sk_buff *msg_queue_tail; | ||
51 | |||
52 | DEFINE_SPINLOCK(tipc_port_list_lock); | 49 | DEFINE_SPINLOCK(tipc_port_list_lock); |
53 | static DEFINE_SPINLOCK(queue_lock); | ||
54 | 50 | ||
55 | static LIST_HEAD(ports); | 51 | static LIST_HEAD(ports); |
56 | static void port_handle_node_down(unsigned long ref); | 52 | static void port_handle_node_down(unsigned long ref); |
@@ -668,215 +664,6 @@ void tipc_port_reinit(void) | |||
668 | spin_unlock_bh(&tipc_port_list_lock); | 664 | spin_unlock_bh(&tipc_port_list_lock); |
669 | } | 665 | } |
670 | 666 | ||
671 | |||
672 | /* | ||
673 | * port_dispatcher_sigh(): Signal handler for messages destinated | ||
674 | * to the tipc_port interface. | ||
675 | */ | ||
676 | static void port_dispatcher_sigh(void *dummy) | ||
677 | { | ||
678 | struct sk_buff *buf; | ||
679 | |||
680 | spin_lock_bh(&queue_lock); | ||
681 | buf = msg_queue_head; | ||
682 | msg_queue_head = NULL; | ||
683 | spin_unlock_bh(&queue_lock); | ||
684 | |||
685 | while (buf) { | ||
686 | struct tipc_port *p_ptr; | ||
687 | struct user_port *up_ptr; | ||
688 | struct tipc_portid orig; | ||
689 | struct tipc_name_seq dseq; | ||
690 | void *usr_handle; | ||
691 | int connected; | ||
692 | int peer_invalid; | ||
693 | int published; | ||
694 | u32 message_type; | ||
695 | |||
696 | struct sk_buff *next = buf->next; | ||
697 | struct tipc_msg *msg = buf_msg(buf); | ||
698 | u32 dref = msg_destport(msg); | ||
699 | |||
700 | message_type = msg_type(msg); | ||
701 | if (message_type > TIPC_DIRECT_MSG) | ||
702 | goto reject; /* Unsupported message type */ | ||
703 | |||
704 | p_ptr = tipc_port_lock(dref); | ||
705 | if (!p_ptr) | ||
706 | goto reject; /* Port deleted while msg in queue */ | ||
707 | |||
708 | orig.ref = msg_origport(msg); | ||
709 | orig.node = msg_orignode(msg); | ||
710 | up_ptr = p_ptr->user_port; | ||
711 | usr_handle = up_ptr->usr_handle; | ||
712 | connected = p_ptr->connected; | ||
713 | peer_invalid = connected && !tipc_port_peer_msg(p_ptr, msg); | ||
714 | published = p_ptr->published; | ||
715 | |||
716 | if (unlikely(msg_errcode(msg))) | ||
717 | goto err; | ||
718 | |||
719 | switch (message_type) { | ||
720 | |||
721 | case TIPC_CONN_MSG:{ | ||
722 | tipc_conn_msg_event cb = up_ptr->conn_msg_cb; | ||
723 | u32 dsz; | ||
724 | |||
725 | tipc_port_unlock(p_ptr); | ||
726 | if (unlikely(!cb)) | ||
727 | goto reject; | ||
728 | if (unlikely(!connected)) { | ||
729 | if (tipc_connect(dref, &orig)) | ||
730 | goto reject; | ||
731 | } else if (peer_invalid) | ||
732 | goto reject; | ||
733 | dsz = msg_data_sz(msg); | ||
734 | if (unlikely(dsz && | ||
735 | (++p_ptr->conn_unacked >= | ||
736 | TIPC_FLOW_CONTROL_WIN))) | ||
737 | tipc_acknowledge(dref, | ||
738 | p_ptr->conn_unacked); | ||
739 | skb_pull(buf, msg_hdr_sz(msg)); | ||
740 | cb(usr_handle, dref, &buf, msg_data(msg), dsz); | ||
741 | break; | ||
742 | } | ||
743 | case TIPC_DIRECT_MSG:{ | ||
744 | tipc_msg_event cb = up_ptr->msg_cb; | ||
745 | |||
746 | tipc_port_unlock(p_ptr); | ||
747 | if (unlikely(!cb || connected)) | ||
748 | goto reject; | ||
749 | skb_pull(buf, msg_hdr_sz(msg)); | ||
750 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
751 | msg_data_sz(msg), msg_importance(msg), | ||
752 | &orig); | ||
753 | break; | ||
754 | } | ||
755 | case TIPC_MCAST_MSG: | ||
756 | case TIPC_NAMED_MSG:{ | ||
757 | tipc_named_msg_event cb = up_ptr->named_msg_cb; | ||
758 | |||
759 | tipc_port_unlock(p_ptr); | ||
760 | if (unlikely(!cb || connected || !published)) | ||
761 | goto reject; | ||
762 | dseq.type = msg_nametype(msg); | ||
763 | dseq.lower = msg_nameinst(msg); | ||
764 | dseq.upper = (message_type == TIPC_NAMED_MSG) | ||
765 | ? dseq.lower : msg_nameupper(msg); | ||
766 | skb_pull(buf, msg_hdr_sz(msg)); | ||
767 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
768 | msg_data_sz(msg), msg_importance(msg), | ||
769 | &orig, &dseq); | ||
770 | break; | ||
771 | } | ||
772 | } | ||
773 | if (buf) | ||
774 | kfree_skb(buf); | ||
775 | buf = next; | ||
776 | continue; | ||
777 | err: | ||
778 | switch (message_type) { | ||
779 | |||
780 | case TIPC_CONN_MSG:{ | ||
781 | tipc_conn_shutdown_event cb = | ||
782 | up_ptr->conn_err_cb; | ||
783 | |||
784 | tipc_port_unlock(p_ptr); | ||
785 | if (!cb || !connected || peer_invalid) | ||
786 | break; | ||
787 | tipc_disconnect(dref); | ||
788 | skb_pull(buf, msg_hdr_sz(msg)); | ||
789 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
790 | msg_data_sz(msg), msg_errcode(msg)); | ||
791 | break; | ||
792 | } | ||
793 | case TIPC_DIRECT_MSG:{ | ||
794 | tipc_msg_err_event cb = up_ptr->err_cb; | ||
795 | |||
796 | tipc_port_unlock(p_ptr); | ||
797 | if (!cb || connected) | ||
798 | break; | ||
799 | skb_pull(buf, msg_hdr_sz(msg)); | ||
800 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
801 | msg_data_sz(msg), msg_errcode(msg), &orig); | ||
802 | break; | ||
803 | } | ||
804 | case TIPC_MCAST_MSG: | ||
805 | case TIPC_NAMED_MSG:{ | ||
806 | tipc_named_msg_err_event cb = | ||
807 | up_ptr->named_err_cb; | ||
808 | |||
809 | tipc_port_unlock(p_ptr); | ||
810 | if (!cb || connected) | ||
811 | break; | ||
812 | dseq.type = msg_nametype(msg); | ||
813 | dseq.lower = msg_nameinst(msg); | ||
814 | dseq.upper = (message_type == TIPC_NAMED_MSG) | ||
815 | ? dseq.lower : msg_nameupper(msg); | ||
816 | skb_pull(buf, msg_hdr_sz(msg)); | ||
817 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
818 | msg_data_sz(msg), msg_errcode(msg), &dseq); | ||
819 | break; | ||
820 | } | ||
821 | } | ||
822 | if (buf) | ||
823 | kfree_skb(buf); | ||
824 | buf = next; | ||
825 | continue; | ||
826 | reject: | ||
827 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
828 | buf = next; | ||
829 | } | ||
830 | } | ||
831 | |||
832 | /* | ||
833 | * port_dispatcher(): Dispatcher for messages destinated | ||
834 | * to the tipc_port interface. Called with port locked. | ||
835 | */ | ||
836 | static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) | ||
837 | { | ||
838 | buf->next = NULL; | ||
839 | spin_lock_bh(&queue_lock); | ||
840 | if (msg_queue_head) { | ||
841 | msg_queue_tail->next = buf; | ||
842 | msg_queue_tail = buf; | ||
843 | } else { | ||
844 | msg_queue_tail = msg_queue_head = buf; | ||
845 | tipc_k_signal((Handler)port_dispatcher_sigh, 0); | ||
846 | } | ||
847 | spin_unlock_bh(&queue_lock); | ||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | /* | ||
852 | * Wake up port after congestion: Called with port locked | ||
853 | */ | ||
854 | static void port_wakeup_sh(unsigned long ref) | ||
855 | { | ||
856 | struct tipc_port *p_ptr; | ||
857 | struct user_port *up_ptr; | ||
858 | tipc_continue_event cb = NULL; | ||
859 | void *uh = NULL; | ||
860 | |||
861 | p_ptr = tipc_port_lock(ref); | ||
862 | if (p_ptr) { | ||
863 | up_ptr = p_ptr->user_port; | ||
864 | if (up_ptr) { | ||
865 | cb = up_ptr->continue_event_cb; | ||
866 | uh = up_ptr->usr_handle; | ||
867 | } | ||
868 | tipc_port_unlock(p_ptr); | ||
869 | } | ||
870 | if (cb) | ||
871 | cb(uh, ref); | ||
872 | } | ||
873 | |||
874 | |||
875 | static void port_wakeup(struct tipc_port *p_ptr) | ||
876 | { | ||
877 | tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref); | ||
878 | } | ||
879 | |||
880 | void tipc_acknowledge(u32 ref, u32 ack) | 667 | void tipc_acknowledge(u32 ref, u32 ack) |
881 | { | 668 | { |
882 | struct tipc_port *p_ptr; | 669 | struct tipc_port *p_ptr; |
@@ -893,50 +680,6 @@ void tipc_acknowledge(u32 ref, u32 ack) | |||
893 | tipc_net_route_msg(buf); | 680 | tipc_net_route_msg(buf); |
894 | } | 681 | } |
895 | 682 | ||
896 | /* | ||
897 | * tipc_createport(): user level call. | ||
898 | */ | ||
899 | int tipc_createport(void *usr_handle, | ||
900 | unsigned int importance, | ||
901 | tipc_msg_err_event error_cb, | ||
902 | tipc_named_msg_err_event named_error_cb, | ||
903 | tipc_conn_shutdown_event conn_error_cb, | ||
904 | tipc_msg_event msg_cb, | ||
905 | tipc_named_msg_event named_msg_cb, | ||
906 | tipc_conn_msg_event conn_msg_cb, | ||
907 | tipc_continue_event continue_event_cb, /* May be zero */ | ||
908 | u32 *portref) | ||
909 | { | ||
910 | struct user_port *up_ptr; | ||
911 | struct tipc_port *p_ptr; | ||
912 | |||
913 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | ||
914 | if (!up_ptr) { | ||
915 | pr_warn("Port creation failed, no memory\n"); | ||
916 | return -ENOMEM; | ||
917 | } | ||
918 | p_ptr = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, | ||
919 | importance); | ||
920 | if (!p_ptr) { | ||
921 | kfree(up_ptr); | ||
922 | return -ENOMEM; | ||
923 | } | ||
924 | |||
925 | p_ptr->user_port = up_ptr; | ||
926 | up_ptr->usr_handle = usr_handle; | ||
927 | up_ptr->ref = p_ptr->ref; | ||
928 | up_ptr->err_cb = error_cb; | ||
929 | up_ptr->named_err_cb = named_error_cb; | ||
930 | up_ptr->conn_err_cb = conn_error_cb; | ||
931 | up_ptr->msg_cb = msg_cb; | ||
932 | up_ptr->named_msg_cb = named_msg_cb; | ||
933 | up_ptr->conn_msg_cb = conn_msg_cb; | ||
934 | up_ptr->continue_event_cb = continue_event_cb; | ||
935 | *portref = p_ptr->ref; | ||
936 | tipc_port_unlock(p_ptr); | ||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | int tipc_portimportance(u32 ref, unsigned int *importance) | 683 | int tipc_portimportance(u32 ref, unsigned int *importance) |
941 | { | 684 | { |
942 | struct tipc_port *p_ptr; | 685 | struct tipc_port *p_ptr; |
@@ -1322,43 +1065,3 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
1322 | } | 1065 | } |
1323 | return -ELINKCONG; | 1066 | return -ELINKCONG; |
1324 | } | 1067 | } |
1325 | |||
1326 | /** | ||
1327 | * tipc_send_buf2port - send message buffer to port identity | ||
1328 | */ | ||
1329 | int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, | ||
1330 | struct sk_buff *buf, unsigned int dsz) | ||
1331 | { | ||
1332 | struct tipc_port *p_ptr; | ||
1333 | struct tipc_msg *msg; | ||
1334 | int res; | ||
1335 | |||
1336 | p_ptr = (struct tipc_port *)tipc_ref_deref(ref); | ||
1337 | if (!p_ptr || p_ptr->connected) | ||
1338 | return -EINVAL; | ||
1339 | |||
1340 | msg = &p_ptr->phdr; | ||
1341 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
1342 | msg_set_destnode(msg, dest->node); | ||
1343 | msg_set_destport(msg, dest->ref); | ||
1344 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | ||
1345 | msg_set_size(msg, BASIC_H_SIZE + dsz); | ||
1346 | if (skb_cow(buf, BASIC_H_SIZE)) | ||
1347 | return -ENOMEM; | ||
1348 | |||
1349 | skb_push(buf, BASIC_H_SIZE); | ||
1350 | skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE); | ||
1351 | |||
1352 | if (in_own_node(dest->node)) | ||
1353 | res = tipc_port_recv_msg(buf); | ||
1354 | else | ||
1355 | res = tipc_send_buf_fast(buf, dest->node); | ||
1356 | if (likely(res != -ELINKCONG)) { | ||
1357 | if (res > 0) | ||
1358 | p_ptr->sent++; | ||
1359 | return res; | ||
1360 | } | ||
1361 | if (port_unreliable(p_ptr)) | ||
1362 | return dsz; | ||
1363 | return -ELINKCONG; | ||
1364 | } | ||